-
引言在信息化社会中,数据库作为数据存储、管理和检索的核心组件,其设计和选择直接影响到系统的性能、可扩展性、可靠性和安全性。其中,分布式数据库与集中式数据库作为两种主流的数据库架构模式,各具特色,适应于不同的应用场景。本文旨在深入剖析分布式数据库与集中式数据库的基本概念、核心特性以及各自的优缺点,以帮助读者在实际项目中做出更为明智的选择。一、分布式数据库:分布式的力量1. 定义与架构分布式数据库是一个由多个物理位置上的数据库节点组成,这些节点通过网络相互连接,共同构成一个逻辑上统一的数据库系统。数据被分割并分散存储在各个节点上,同时,数据库管理系统(DBMS)负责协调节点间的操作,确保数据的一致性和完整性。2. 主要特性高可用性与容错性:由于数据分散存储,即使个别节点出现故障,其他节点仍能提供服务,确保整体系统的持续运行。高性能与可扩展性:通过并行处理和负载均衡技术,分布式数据库能够利用多节点的计算资源加速查询和更新操作。随着业务增长,只需增加节点即可实现水平扩展。灵活的数据分布:可根据业务需求和数据访问模式,动态调整数据在节点间的分布,实现最优的资源利用。3. 缺点与挑战系统复杂性:跨节点的数据同步、一致性控制、故障恢复等机制增加了系统的复杂性,对管理和运维能力提出了更高要求。数据安全与隐私:分布式环境中数据传输与共享的风险增大,需要部署严格的安全策略和加密技术来保障数据安全。一致性保证:保持数据全局一致性的难度增加,尤其是面对并发操作和网络延迟时,需要采用如两阶段提交(2PC)、分布式事务等复杂技术。二、集中式数据库:单一源头的稳健1. 定义与架构集中式数据库是指所有数据存储、管理和访问均集中在单一物理位置(如一台服务器或数据中心)的数据库系统。用户通过网络连接到中心节点进行数据操作。2. 主要特性简单性与易管理:单一数据源简化了数据访问路径,便于数据的协调与管理,降低了运维复杂度。数据冗余低:数据集中存放减少了数据副本,有利于数据一致性维护,同时也节省了存储空间。经济性:相较于分布式架构,初期建设和运维成本通常较低,尤其适合规模适中、数据量稳定且对实时性要求较高的场景。3. 缺点与局限单点风险:集中式架构下,一旦中心节点发生故障,可能导致整个系统不可用,影响服务连续性。扩展性受限:随着数据量和访问量的增长,垂直扩展(提升单台服务器性能)存在物理极限,且成本高昂。水平扩展则需借助分库分表等技术,但会引入额外复杂性。数据访问压力:所有用户请求均指向同一节点,可能导致数据流量过大,影响响应速度。三、应用场景与选择考量分布式数据库在以下场景中表现出色:大数据处理:大规模数据集、高并发访问、实时分析等需要高吞吐量和快速响应的业务。互联网服务:社交网络、电商平台、在线游戏等用户基数大、数据增长迅速的行业。地理分布:跨国公司、云服务提供商,需要在全球范围内就近提供服务,降低延迟。集中式数据库适用于:中小型企业:初期数据规模较小,对成本敏感,且业务稳定性要求较高的情况。内部管理系统:如企业资源规划(ERP)、客户关系管理(CRM)等,数据量相对固定,访问模式较为明确。
-
在数据仓库领域,我们常常会遇到一些缩写,比如DWD、DWB和DWS。这些缩写代表着数据仓库的不同层次,对于理解和构建数据仓库体系具有重要意义。下面,我们就来详细解释一下这些缩写的含义。DWD(Data Warehouse Discover) DWD,即Data Warehouse Discover,代表着数据仓库的探索层。在这个阶段,主要的目标是进行数据探查和数据清洗。DWD的数据源可能包括多个系统,如ERP、CRM、OA等。这些系统中的数据格式、数据类型、数据关系等都可能不同,因此需要进行数据清洗和整合,以便于后续的数据分析和决策支持。DWB(Data Warehouse Build) DWB,即Data Warehouse Build,代表着数据仓库的构建层。在这个阶段,主要的目标是将DWD中的数据进行整合和清洗,构建出符合业务需求的数据模型。这个模型通常是一个多维度的数据立方体,可以支持多种数据分析算法和决策支持应用。DWB的数据源可以是多个数据仓库的整合,也可以是多个数据源的整合。DWS(Data Warehouse Services) DWS,即Data Warehouse Services,代表着数据仓库的服务层。在这个阶段,主要的目标是将DWB中的数据进行加工和处理,以支持决策支持和数据分析应用。DWS的数据源可以是多个数据仓库的整合,也可以是多个数据源的整合。DWS的数据模型应该与具体的业务需求相结合,支持多种决策支持和数据分析应用。总结一下,DWD、DWB和DWS是数据仓库的三个重要层次,分别代表着数据仓库的探索、构建和服务三个阶段。在构建数据仓库时,我们需要明确每个阶段的目标和任务,以及每个阶段所需要的数据源和数据模型。只有理解了这些缩写背后的含义和任务,我们才能更好地理解和应用数据仓库的知识和技术。在实际的数据仓库项目中,这些缩写都有着重要的应用价值。比如在构建一个新的人力资源管理系统的数据仓库时,我们可以首先使用DWD进行数据探查和清洗,然后使用DWB构建出符合人力资源管理业务需求的数据模型,最后使用DWS进行数据的分析和决策支持。除了这些缩写,数据仓库中还涉及到许多其他的概念和技术,比如ETL(Extract-Transform-Load,指数据的抽取、转换和加载)、ELT(Extract-Load-Transform,指数据的抽取、加载和转换)、数据模型设计、元数据管理、数据质量等等。理解了这些概念和技术的含义和应用方法,我们才能更好地构建和应用数据仓库。
-
在数据库设计中,选择合适的数据类型对于保证数据的完整性和效率至关重要。BLOB、CLOB 和 NVARCHAR 是数据库中常见的三种数据类型,它们各自有不同的用途和特点。本文将详细介绍这三种数据类型的区别,以及它们各自的应用场景。BLOB(Binary Large Object)BLOB 是一种用于存储大量二进制数据的数据类型,如图片、音频、视频文件等。它通常用于存储非文本数据,最大大小可以达到数GB。特点存储二进制数据:BLOB 可以存储任何类型的二进制数据。大容量:BLOB 适合存储大文件,其容量通常远大于其他数据类型。应用场景多媒体内容管理:如存储图片、视频、音频等多媒体文件。文档管理:如存储 Word、PDF、Excel 等文档。CLOB(Character Large Object)CLOB 是一种用于存储大量文本数据的数据类型,如大型文档、XML 文件等。它通常用于存储字符数据,最大大小也可以达到数GB。特点存储文本数据:CLOB 用于存储大量的文本内容。支持字符集:CLOB 可以指定字符集,以支持不同的语言和编码。应用场景内容管理系统:如存储文章、新闻、博客等文本内容。数据仓库:存储日志文件、报告等大量文本数据。NVARCHARNVARCHAR 是一种可变长度的字符串数据类型,它可以存储 Unicode 字符。NVARCHAR 通常用于存储少量的文本数据,如用户名、地址等。特点Unicode 支持:NVARCHAR 可以存储任何语言的字符,包括中文字符、日文字符等。可变长度:NVARCHAR 的长度可以根据实际存储的数据动态变化,节省空间。应用场景国际化应用:当应用程序需要支持多语言时,NVARCHAR 是理想的选择。常规文本字段:如存储用户输入的评论、描述等信息。结语BLOB、CLOB 和 NVARCHAR 是数据库中用于存储不同类型数据的三大数据类型。BLOB 和 CLOB 适用于存储大型的二进制和文本数据,而 NVARCHAR 则适用于存储少量的、需要支持多语言的文本数据。了解它们之间的区别和各自的应用场景,可以帮助数据库设计者做出更合理的数据类型选择,从而优化数据库的性能和可扩展性。希望本文能帮助您更好地理解这三种数据类型的使用。
-
在数据库管理中,随着数据量的不断增长,单台服务器可能无法满足数据的存储和查询需求。为了解决这个问题,数据库分区技术应运而生。分区是将大表或索引分解为更小、更可管理的部分的过程。本文将详细介绍数据库分区,以及水平分区和垂直分区的区别。数据库分区的好处提高性能:通过将数据分散到不同的分区,查询可以并行执行,从而提高性能。增强可管理性:分区使得数据管理更加方便,例如备份和恢复可以分区进行。提高可用性:分区可以在多台服务器上分布,即使某台服务器发生故障,其他分区的数据仍然可用。水平分区(Horizontal Partitioning)水平分区也称为行分区,它是将表的行分散到不同的表中。每个分区包含的行数可能相同,也可能不同。特点相同数据结构:所有分区都具有相同的列和数据类型。数据分布:数据按行分布,通常基于某种规则,如范围(如日期范围)、列表(如特定的值列表)或哈希(如根据哈希函数计算的结果)。应用场景时间序列数据:例如,可以将订单表按年份分区,每个分区存储不同年份的订单。大规模数据集:当表中的数据量非常大时,水平分区可以有效地管理和查询数据。垂直分区(Vertical Partitioning)垂直分区也称为列分区,它是将表的列分散到不同的表中。每个分区包含的列可能不同。特点不同数据结构:每个分区可能包含不同的列。数据关联:通常通过外键或相同的键列来保持数据之间的关联。应用场景宽表:当表中的列非常多时,可以将不常一起查询的列分开存储,以提高查询效率。数据隐私和安全:敏感数据可以单独分区,并采取额外的安全措施。水平分区与垂直分区的区别数据分布方式:水平分区按行分布数据,而垂直分区按列分布数据。数据结构:水平分区中的所有分区具有相同的列,垂直分区中的每个分区可能包含不同的列。应用场景:水平分区适用于按行访问数据,垂直分区适用于按列访问数据。结语数据库分区是一种提高数据库性能和可管理性的有效技术。水平分区和垂直分区各有优势,应根据具体的应用场景和需求选择合适的分区策略。在实际应用中,还可以将水平分区和垂直分区结合使用,以实现更复杂的数据分布和管理需求。希望本文能帮助您更好地理解数据库分区技术。
-
你认为,学好数据库,要掌握哪些知识点。欢迎畅所欲言
-
一、技术干货GaussDB数据库学院干货汇总来源:cid:link_6高斯Redis系列文章导航来源:cid:link_7数据库1分钟DBA系列大合集来啦,请速速收藏:)来源:cid:link_8GaussDB WDR分析之集群报告篇来源: cid:link_1手动挡变自动挡---OpenEuler配置OpenGauss开机自启动来源:cid:link_2GaussDB分区表自动新增分区来源:cid:link_3二、实用教程PostgreSQL数据库的插入和查询分析PPT本文档以从单线程单个插入数据、多线程单个插入数据、使用COPY命令插入数据,分析这些操作对PostgreSQL数据库的性能影响进行了详细的分析。 链接: cid:link_9 提取码: szcm来源:cid:link_4PostgreSQL 的数据库开发实践PPT本文档以体操比赛管理系统为例,讲述了利用PostgreSQL数据库开发一个数据库管理系统,具体包含的PostgreSQL安装、建库、建表;数据库的ER建模;以及基于三层架构的数据库应用开发。 链接: cid:link_10 提取码: frjj数据库学习PPT附件介绍了武汉大学弘毅学堂计算机专业的同学学完数据库系统实现后,开发一个移动端数据库的教学课件。该课件重点介绍了该数据库开发的技术路线。文档可以通过百度网盘进行下载。 cid:link_11 提取码: vgk7来源:cid:link_0三、问题答疑openGauss 据说已经支持大小写不敏感的like匹配,问题来了GaussDB是否也已经支持大小写不敏感的like匹配?答:大小写敏感用like,大小写不敏感用ilike:cid:link_5来源:cid:link_5
-
数据库论坛2024年3月份热门问题汇总1.华为GaussDB 200 安装Manager失败怎么办?cid:link_1优质解答:当提示 "shmmax 值太小" 时,通常指的是共享内存段的最大大小设置过小。共享内存是一种进程间通信的方式,在 Linux 系统中通过共享内存可以实现多个进程之间的数据共享。要解决 "shmmax 值太小" 的问题,可以按照以下步骤进行调整:查看当前 shmmax 值:可以使用以下命令查看当前系统的 shmmax 值:bash sysctl kernel.shmmax临时调整 shmmax 值:可以使用 sysctl 命令临时调整 shmmax 值,例如将 shmmax 设置为 2GB:bash sudo sysctl -w kernel.shmmax=2147483648永久调整 shmmax 值:如果想要永久性地修改 shmmax 值,在 /etc/sysctl.conf 文件中添加或编辑以下行:kernel.shmmax = 2147483648使修改生效:在修改完 /etc/sysctl.conf 文件后,可以使用以下命令使修改生效:bash sudo sysctl -p验证修改是否生效:再次运行 sysctl kernel.shmmax 命令来验证 shmmax 值是否已经修改为期望的大小。通过以上步骤,您可以调整系统的 shmmax 值,以满足程序对共享内存大小的需求。请根据具体情况选择临时或永久性的调整方式,并确保调整后的值符合您的实际需求。2.请问:openGauss 据说已经支持大小写不敏感的like匹配,问题来了GaussDB是否也已经支持大小写不敏感的like匹配?cid:link_2大小写敏感用like,大小写不敏感用ilike3.springboot项目使用mybatis-plus集成GaussDB,批量插入报错cid:link_3JDBC连接串上添加&reWriteBatchedInserts=true。使用该参数时,需设置batchMode=offjdbc:postgresql://host1:port1,host2:port2,host3:port3/database?targetServer=master&batchMode=off&reWriteBatchedInserts=true4.GaussDB 分布式版 对postgis的支持情况cid:link_0GaussDB不提供PostGIS插件,可使用openGauss提供的PostGIS Extension(版本为PostGIS-2.4.2)插件进行安装5.GaussDB 有哪些开源 ETL 工具可以使用ETL除了官方的工具DataArts Studio 想请教下还有哪些开源的工具也可以做Guassdb的ETL吗?cid:link_4优质解答:Kettle是一款免费的国外开源ETL工具,使用广泛,是一款目前来看市面上功能最强大的开源ETL工具,通过Kettle可用于数据抽取、转换和加载实现数据快速入仓和分析。下面简单说一下Kettle的优缺点:优点:(1)提供了直观的图形化用户界面,用户可以通过拖放和连接转换步骤来构建数据集成流程,这种可视化的开发方式使得非技术人员也能够轻松上手,并加快了开发效率。(2)Kettle提供了丰富的转换步骤和功能,使用户能够对数据进行清洗、过滤、转换和合并等操作,它支持各种数据处理技术,包括字符串操作、日期处理、聚合计算、条件判断等,以满足复杂的数据转换需求。6.
-
我最近开发了一个maven项目,想使用spark读取/写入greenplum的数据,但是由于jdbc的传输速度限制。所以想采用greenplum-spark connect这个连接器。当我使用--jars将项目和这个依赖包一起提交上去的时候出现了jar包冲突 报错:classnotfound。所以我又尝试使用jarjar.jar修改相应的包名 但是现在又出现了新的问题,代码中的postgresql依赖找不到对应的class类名报错。 既然外部没办法搞定就从内部项目入手 …… 由于这个依赖属于第三方并不是maven仓库官方提供所以没法加载进入项目中。我尝试加入私有仓库然后再放入我的本地项目中使用maven-shade-plugin将类名包名重定向。不知道是不是第三方依赖的原因,只要提交到cluster上后就会显示找不到类,相当于没有加上这个greenplum-spark依赖。请各位大佬看看是什么原因。 我这边在本地用idea或者Local模式提交都是可以成功的
-
数据库:因为mysql逐渐向商业化转进,这里提出了另一个数据库Mariadb两者的操作,性能基本一致(不过在华为云服务里面基本使用的是MYSQL,但是操作相似所以不影响就是的了初始化Mariadb服务yum install -y mariadb-server在安装后通过systemctl来启动和开机自启然后是对数据库的初始化过程mysql_secure_installation在防火墙开启的情况下我们需要对mysql服务放行:firewall-cmd --permanent --add-service=mysqlfirewall-cmd --reload通过初始化的时候设置的用户名和密码来实现登入数据库mysql -u root -p通过华为云的DAS发现不可以的实现远程访问需要在数据库中加入如下权限开启 grant all privileges on *.* to 'root'@'%' identified by 'Huawei@111' with grant option;flush privileges;就可以实现图形化界面来管理数据库了通过图形化界面方面的实现创建,管理用户,创建,管理表等sql语句简单了解;在创建之后就需要对数据库实现切换use mybook创建表create table mybook (name char(15),price int,pages int);添加数据insert into mybook(name,page,price) values ('mybook','145','25');查找数据select name,price,page from mybook;查询语句可以灵活的使用where命令来确定查询范围修改数据update mybook set price=30 where pages='145';update修改一个值的时候需要一个定位点删除数据delete from mybook:完全删除数据表删除同样可以使用where来定点delete from mybook where pages>100; 简单脚本编写:这里直接例子来看,脚本的基本结构#! /bin/sh:这里做为脚本的开始,表示的是脚本需要使用sh解释器来工作接下来为执行的命令,和linux命名行的命令差不读最后对脚本授权:chmod 777 ***.sh就可以执行脚本里面的内容(不开权限是执行不了内容的
-
1. 断电后系统的 hostname和cluster配置文件中的不一致,导致openGauss不能启动, 2. 我修改了hostname文件,改回去和cluster配置文件一致的名字,3. reboot重启系统,4. 重启openGauss会出现这几个warning怎么消除呢?
-
多年不用PageHelper了,最近新入职的公司,采用了此工具集成的框架,作为一个独立紧急项目开发的基础。项目开发起来,还是手到擒来的,但是没想到,最终测试的时候,深深的给我上了一课。我的项目发生了哪些奇葩现象?一切的问题都要从我接受的项目开始说起, 在开发这个项目的过程中,发生了各种奇葩的事情, 下面我简单说给你们听听:账号重复注册?你肯定在想这是什么意思? 就是字面意思,已经注册的账号,可以再次注册成功!!!else if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(username)) ||"匿名用户".equals(username)){ // 注册用户已存在 msg = "注册用户'" + username + "'失败"; }如上所示: checkUserNameUnique(username)用来验证数据库是否存在用户名:<select id="checkUserNameUnique" parameterType="String" resultType="int"> select count(1) from sys_user where user_name = #{userName} limit 1 </select>正常来说,是不会有问题的,那么原因我们后面讲,接着看下一个问题。查询全部分类的下拉列表只能查出5条数据?如上所示,明明有十多个结果,怎么只能返回5个?我也没有添加分页参数啊?相信用过PageHelper的同学已经知道问题出在哪里了。修改用户密码报错?当管理员在后台界面重置用户的密码的时候,居然报错了?报错信息清晰的告诉了我:sql语句异常,update语句不认识 “Limit 5”到此为止,报错信息已经告诉了我,我的sql被拼接了该死的“limit”分页参数。小结上面提到的几个只是冰山一角,在我使用的过程中,还有各种涉及到sql的地方,会因为这个分页参数导致的问题,我可以分为两种:1)直接导致报错的:明确报错原因的比如insert、update语句等,不支持limit,会直接报错。2)导致业务逻辑错误,但是代码没有错误提示如我上面提到的用户可以重复注册,却没有报错,实际在代码当中是有报错的,但是当前方法对异常进行了throw,最终被全局异常捕获了。不分页的sql被拼接了limit,导致没有报错,但是数据返回量错误。异常不是每次出现,是有一定纪律的,但是触发几率较高,原因在后面会逐渐脱出。PageHelper是怎么做到上面的问题的?PageHelper使用我这里只讲解项目基于的框架的使用方式。代码如下:@GetMapping("/cms/cmsEssayList") public TableDataInfo cmsEssayList(CmsBlog cmsBlog) { //状态为发布 cmsBlog.setStatus("1"); startPage(); List<CmsBlog> list = cmsBlogService.selectCmsBlogList(cmsBlog); return getDataTable(list); }使用起来还是很简单的,通过 startPage()指定分页参数,通过getDataTable(list)对结果数据封装成分页的格式。有些同学会问,这也没没传分页参数啊,并且实体类当中也没有,这就是比较有意思的点,下一小结就来聊聊源码。startPage()干啥了?protected void startPage(){ // 通过request去获取前端传递的分页参数,不需控制器要显示接收 PageDomain pageDomain = TableSupport.buildPageRequest(); Integer pageNum = pageDomain.getPageNum(); Integer pageSize = pageDomain.getPageSize(); if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) { String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); Boolean reasonable = pageDomain.getReasonable(); // 真正使用pageHelper进行分页的位置 PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable); } }PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable)的参数分别是:pageNum:页数pageSize:每页数据量orderBy:排序reasonable:分页合理化,对于不合理的分页参数自动处理,比如传递pageNum是小于0,会默认设置为1.继续跟踪,连续点击startpage构造方法到达如下位置:/** * 开始分页 * * @param pageNum 页码 * @param pageSize 每页显示数量 * @param count 是否进行count查询 * @param reasonable 分页合理化,null时用默认配置 * @param pageSizeZero true且pageSize=0时返回全部结果,false时分页,null时用默认配置 */ public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) { Page<E> page = new Page<E>(pageNum, pageSize, count); page.setReasonable(reasonable); page.setPageSizeZero(pageSizeZero); // 1、获取本地分页 Page<E> oldPage = getLocalPage(); if (oldPage != null && oldPage.isOrderByOnly()) { page.setOrderBy(oldPage.getOrderBy()); } // 2、设置本地分页 setLocalPage(page); return page; }到达终点位置了,分别是:getLocalPage()和setLocalPage(page),分别来看下:getLocalPage()进入方法:/** * 获取 Page 参数 * * @return */ public static <T> Page<T> getLocalPage() { return LOCAL_PAGE.get(); }看看常量LOCAL_PAGE是个什么路数?protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal<Page>();好家伙,是ThreadLocal,学过java基础的都知道吧,独属于每个线程的本地缓存对象。当一个请求来的时候,会获取持有当前请求的线程的ThreadLocal,调用LOCAL_PAGE.get(),查看当前线程是否有未执行的分页配置。setLocalPage(page)此方法显而易见,设置线程的分页配置:protected static void setLocalPage(Page page) { LOCAL_PAGE.set(page); }小结经过前面的分析,我们发现,问题似乎就是这个ThreadLocal导致的。是否在使用完之后没有进行清理?导致下一次此线程再次处理请求时,还在使用之前的配置?我们带着疑问,看看mybatis时如何使用pageHelper的。mybatis使用pageHelper分析我们需要关注的就是mybatis在何时使用的这个ThreadLocal,也就是何时将分页餐数获取到的。前面提到过,通过PageHelper的startPage()方法进行page缓存的设置,当程序执行sql接口mapper的方法时,就会被拦截器PageInterceptor拦截到。PageHelper其实就是mybatis的分页插件,其实现原理就是通过拦截器的方式,pageHelper通PageInterceptor实现分页效果,我们只关注intercept方法:@Override public Object intercept(Invocation invocation) throws Throwable { try { Object[] args = invocation.getArgs(); MappedStatement ms = (MappedStatement) args[0]; Object parameter = args[1]; RowBounds rowBounds = (RowBounds) args[2]; ResultHandler resultHandler = (ResultHandler) args[3]; Executor executor = (Executor) invocation.getTarget(); CacheKey cacheKey; BoundSql boundSql; // 由于逻辑关系,只会进入一次 if (args.length == 4) { //4 个参数时 boundSql = ms.getBoundSql(parameter); cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql); } else { //6 个参数时 cacheKey = (CacheKey) args[4]; boundSql = (BoundSql) args[5]; } checkDialectExists(); //对 boundSql 的拦截处理 if (dialect instanceof BoundSqlInterceptor.Chain) { boundSql = ((BoundSqlInterceptor.Chain) dialect).doBoundSql(BoundSqlInterceptor.Type.ORIGINAL, boundSql, cacheKey); } List resultList; //调用方法判断是否需要进行分页,如果不需要,直接返回结果 if (!dialect.skip(ms, parameter, rowBounds)) { //判断是否需要进行 count 查询 if (dialect.beforeCount(ms, parameter, rowBounds)) { //查询总数 Long count = count(executor, ms, parameter, rowBounds, null, boundSql); //处理查询总数,返回 true 时继续分页查询,false 时直接返回 if (!dialect.afterCount(count, parameter, rowBounds)) { //当查询总数为 0 时,直接返回空的结果 return dialect.afterPage(new ArrayList(), parameter, rowBounds); } } resultList = ExecutorUtil.pageQuery(dialect, executor, ms, parameter, rowBounds, resultHandler, boundSql, cacheKey); } else { //rowBounds用参数值,不使用分页插件处理时,仍然支持默认的内存分页 resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql); } return dialect.afterPage(resultList, parameter, rowBounds); } finally { if(dialect != null){ dialect.afterAll(); } } }如上所示是intecept的全部代码,我们下面只关注几个终点位置:设置分页:dialect.skip(ms, parameter, rowBounds)此处的skip方法进行设置分页参数,内部调用方法:Page page = pageParams.getPage(parameterObject, rowBounds);继续跟踪getPage(),发现此方法的第一行就获取了ThreadLocal的值:Page page = PageHelper.getLocalPage();统计数量:dialect.beforeCount(ms, parameter, rowBounds)我们都知道,分页需要获取记录总数,所以,这个拦截器会在分页前先进行count操作。如果count为0,则直接返回,不进行分页://处理查询总数,返回 true 时继续分页查询,false 时直接返回 if (!dialect.afterCount(count, parameter, rowBounds)) { //当查询总数为 0 时,直接返回空的结果 return dialect.afterPage(new ArrayList(), parameter, rowBounds); }afterPage其实是对分页结果的封装方法,即使不分页,也会执行,只不过返回空列表。分页:ExecutorUtil.pageQuery在处理完count方法后,就是真正的进行分页了:resultList = ExecutorUtil.pageQuery(dialect, executor, ms, parameter, rowBounds, resultHandler, boundSql, cacheKey);此方法在执行分页之前,会判断是否执行分页,依据就是前面我们通过ThreadLocal的获取的page。当然,不分页的查询,以及新增和更新不会走到这个方法当中。非分页:executor.query而是会走到下面的这个分支:resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);我们可以思考一下,如果ThreadLoad在使用后没有被清除,当执行非分页的方法时,那么就会将Limit拼接到sql后面。为什么不分也得也会拼接?我们回头看下前面提到的dialect.skip(ms, parameter, rowBounds):如上所示,只要page被获取到了,那么这个sql,就会走前面提到的ExecutorUtil.pageQuery分页逻辑,最终导致出现不可预料的情况。其实PageHelper对于分页后的ThreaLocal是有清除处理的。清除TheadLocal在intercept方法的最后,会在sql方法执行完成后,清理page缓存:finally { if(dialect != null){ dialect.afterAll(); } }看看这个afterAll()方法:@Override public void afterAll() { //这个方法即使不分页也会被执行,所以要判断 null AbstractHelperDialect delegate = autoDialect.getDelegate(); if (delegate != null) { delegate.afterAll(); autoDialect.clearDelegate(); } clearPage(); }只关注 clearPage():/** * 移除本地变量 */ public static void clearPage() { LOCAL_PAGE.remove(); }小结到此为止,关于PageHelper的使用方式就讲解完了。整体看下来,似乎不会存在什么问题,但是我们可以考虑集中极端情况:如果使用了startPage(),但是没有执行对应的sql,那么就表明,当前线程ThreadLocal被设置了分页参数,可是没有被使用,当下一个使用此线程的请求来时,就会出现问题。如果程序在执行sql前,发生异常了,就没办法执行finally当中的clearPage()方法,也会造成线程的ThreadLocal被污染。所以,官方给我们的建议,在使用PageHelper进行分页时,执行sql的代码要紧跟startPage()方法。除此之外,我们可以手动调用clearPage()方法,在存在问题的方法之前。需要注意:不要分页的方法前手动调用clearPage,将会导致你的分页出现问题。还有人问为什么不是每次请求都出错?这个其实取决于我们启动服务所使用的容器,比如tomcat,在其内部处理请求是通过线程池的方式。甚至现在的很多容器是基于netty的,都是通过线程池,复用线程来增加服务的并发量。假设线程1持有没有被清除的page参数,不断调用同一个方法,后面两个请求使用的是线程2和线程3没有问题,再一个请求轮到线程1了,此时就会出现问题了。总结关于PageHelper的介绍就这么多,真的是折磨我好几天,要不是项目紧急,来不及替换,我一定不会使用这个组件。莫名其妙的就会有个方法出现问题,一通排查,发现都是这个PageHelper导致的。虽然我已经全局搜索使用的地方,保证startPage()后紧跟sql命令,但是仍然有嫌犯潜逃,只能在有问题的方法使用clearPage()来打补丁。虽然PageHelper给我带来一些困扰,耗费了一定的时间,但是定位问题的过程中,也学习了mybatis和pagehepler的实现方式,对于热爱源码阅读的同学来说还是有一定的提升的。
-
GaussDB(DWS) 全节点CPU高且无异常SQL排查方法https://bbs.huaweicloud.com/forum/thread-02127142398272625007-1-1.htmlDDD领域驱动设计详解https://bbs.huaweicloud.com/forum/thread-0285142744510322015-1-1.html领域驱动设计介绍(二)https://bbs.huaweicloud.com/forum/thread-0285142744827363016-1-1.html领域驱动和其他设计模式的对比https://bbs.huaweicloud.com/forum/thread-0267142745213117015-1-1.htmlSQL中等值匹配和in匹配哪个效率高https://bbs.huaweicloud.com/forum/thread-0224142745386602015-1-1.htmlmysql中INSERT INTO ... ON DUPLICATE KEY UPDATE介绍https://bbs.huaweicloud.com/forum/thread-0235142745913553018-1-1.htmlgaussDB的gsql访问工具导出数据时,如果当前字符串数据存在双引号时,会出现多次转义https://bbs.huaweicloud.com/forum/thread-0224143792598916029-1-1.html group by 为什么比 distinct 效率高https://bbs.huaweicloud.com/forum/thread-0240144139360376011-1-1.htmlpostgresql 性能优化https://bbs.huaweicloud.com/forum/thread-0264144139475618011-1-1.html深入理解 MySQL 底层实现https://bbs.huaweicloud.com/forum/thread-02101144139259289014-1-1.htmlMybatis+mysql批量插入性能分析测试https://bbs.huaweicloud.com/forum/thread-02109144139187419013-1-1.htmlmysql 间隙锁https://bbs.huaweicloud.com/forum/thread-0270144139126002011-1-1.htmlInnoDB的行记录格式, Compact, Redundant, Compressed, Dynamichttps://bbs.huaweicloud.com/forum/thread-02127144139077746007-1-1.htmlMySQL查询锁表语句详情https://bbs.huaweicloud.com/forum/thread-02109144138910949012-1-1.html
-
新的U-Lab环境 LINK怎么连接Oracle数据库,我看数据源选项里没有Oracle这一项租户名:Hidsic
-
GaussDB 的数据库复制工具DRS支持oracle9i的迁移吗cid:link_1 通过drs工具进行oracle数据库到gaussdb数据库的全量数据同步,但不支持oracle9i 数据库论坛11月热门问题合集我要如何从0到开始学习GaussDB目前,我是一名Java后端开发学习人员,对MySQL具有一定的认识,现在我想学习GaussDB,我应该如何做?问题链接:cid:link_2优质解答:您好,这里有个学习的经验帖子,看看能不能帮到你cid:link_6另外,如果还想了解,可以去数据库课程学习cid:link_7我的云服务器 和云数据库 MySQL 在不同地域下(如 C在广州,MySQL 在上海),可以直接内网访问吗?问题链接:cid:link_3您好,跨地域内网默认不能访问,不同区域的云服务之间内网互不相通。您可以通过公网访问,或者通过云连接/VPN打通网络实现内网访问。云数据库 MySQL 执行某个存储过程中误删了部分未备份的数据,能否还原数据?问题链接: cid:link_0优质解答: 如果在云数据库 MySQL 中执行某个存储过程时误删了一些未备份的数据,数据恢复可能会比较困难。但是,还是有一些可能的方法可以尝试:如果开启了binlog日志,可以使用binlog还原数据。基于binlog的增量备份及数据还原方法在很多情况下是有效的,但需要注意的是,这个方法对于删除操作可能存在一定的局限性。可以尝试使用备份还原的方法。如果之前有定期备份数据,那么可以通过还原备份数据来找回误删除的数据。如果有对删除的数据进行了深度解析,那么也可以尝试解析记录来恢复数据。请注意,以上方法并不能保证100%能够恢复数据,因此在进行任何数据恢复操作之前,强烈建议先备份整个数据库,以防止任何意外的数据丢失Gauss DB DWS 通常跑批加工场景下,都是大数量做关联操作,通常不建议使用索引。有些时候因为计划误判导致使用索引的可能会导致严重的性能问题。这句话怎么理解?网址: cid:link_4优质解答:在Gauss DB DWS中,当进行大批量的关联操作时,通常不建议使用索引。这是因为在大批量数据场景下,索引的使用可能会导致性能问题。首先,索引是一种用于快速检索数据的数据库结构。它可以帮助数据库系统快速定位到满足查询条件的数据行。然而,在大批量数据关联操作的场景下,索引可能并不总是最有效的选择。在大批量关联操作中,数据通常以大规模的形式进行处理和交换。如果使用索引,数据库系统需要在关联操作期间频繁地访问索引结构,这可能会导致额外的I/O操作和计算开销。相比之下,全表扫描可能更加高效,因为它可以避免索引查找的开销,并直接读取整个表的数据。此外,由于数据库优化器在选择执行计划时会根据统计信息和成本估计进行决策,有时候可能会出现计划误判的情况。即使索引不是最优选择,优化器仍然可能会选择使用索引。这种情况下,由于索引的使用导致额外的开销和性能下降,可能会出现严重的性能问题。GaussDB(DWS)中,什么是存算分离表,它与传统数据库中的表有什么不同cid:link_5优质解答:GaussDB(DWS)中的存算分离表是一种新型的表存储模式,它将表的存储和计算分离,以提高数据处理效率和灵活性。存算分离表的主要特点是将表的存储和计算分布在不同的节点上,通过高速网络进行连接和通信。这种分离的设计使得存储和计算可以独立扩展,从而提高了整个系统的可扩展性和灵活性。相比之下,传统数据库中的表通常采用存储和计算紧密耦合的方式,即表的存储和计算都在同一个数据库服务器上执行。这种方式在处理小规模和中等规模的数据时可能表现良好,但在处理大规模数据时可能会面临性能瓶颈和扩展性问题。存算分离表的优势在于:灵活性:由于存储和计算可以独立扩展,因此可以根据实际需求灵活地调整存储和计算资源,以适应不同的数据处理需求。可扩展性:存算分离表可以水平扩展,通过增加节点来扩展系统的处理能力,从而满足大规模数据处理的需求。高性能:通过将计算和存储分离,可以减少数据在节点之间的传输延迟,提高数据处理效率。成本效益:存算分离表可以根据实际需求进行弹性扩缩容,从而降低了硬件成本和维护成本。
-
分布式数据库:概念与解析在现代数据驱动的世界中,数据库管理系统(DBMS)是存储、检索、定义和管理大量数据的核心组件。随着数据量的增长和业务需求的复杂化,传统的单机数据库在某些场景下可能无法满足性能和可伸缩性的需求。这时,分布式数据库(Distributed Database)便成为了一个重要的解决方案。什么是分布式数据库?分布式数据库是一个数据库系统,其中的数据存储在多个物理位置,这些位置通过网络相互连接。每个位置都有一个数据库管理系统(DBMS)的实例,可以独立地处理本地数据。这些DBMS实例可以协同工作,以提供全局的数据访问和管理能力。主要特点:物理分布:数据在物理上分布在多个节点或站点上。逻辑统一:尽管数据在物理上是分布的,但从用户和应用程序的角度来看,它们访问的是一个逻辑上统一的数据库。网络互联:各个节点通过网络相互连接,支持数据的传输和同步。透明性:用户通常不需要知道数据实际存储在哪个节点上,也不需要关心数据的分布和复制细节。可伸缩性和高可用性:通过增加节点,系统可以水平扩展以满足更高的性能需求。同时,数据的冗余存储可以提高系统的可用性和容错能力。分布式数据库的类型根据数据的分布方式和系统的架构,分布式数据库可以分为几种类型:分片式(Sharded):数据被水平分割成多个片段(shards),每个片段存储在不同的节点上。每个节点独立地管理其本地片段,而全局的数据访问和查询需要通过某种形式的分片键或路由机制来实现。复制式(Replicated):为了提高可用性和性能,数据在多个节点上进行冗余存储。每个节点都拥有完整的数据副本,可以独立地处理查询和事务。复制式数据库需要解决数据一致性和冲突解决的问题。混合式:结合了分片式和复制式的特点。数据既被分片以提高可伸缩性,又在多个节点上进行复制以提高可用性和性能。分布式NoSQL数据库:这是一种特殊的分布式数据库,它采用非关系型数据模型(如键值对、文档、列族或图形),并且通常设计用于处理大规模的非结构化或半结构化数据。分布式数据库的优势和挑战优势:可伸缩性:通过增加节点来扩展系统的处理能力。高可用性:数据的冗余存储和节点的故障恢复能力提高了系统的可用性。性能优化:数据可以更接近用户存储和处理,减少网络延迟。灵活性:可以根据业务需求灵活地调整数据分布和复制策略。挑战:数据一致性:在分布式环境中维护数据的一致性和完整性是一个复杂的问题。网络通信:节点之间的网络通信可能成为性能和可靠性的瓶颈。复杂性:分布式系统的设计、实现和维护通常比单机数据库系统更复杂。安全性:需要额外的安全措施来保护分布在多个位置的数据。
上滑加载中
推荐直播
-
HDC深度解读系列 - Serverless与MCP融合创新,构建AI应用全新智能中枢2025/08/20 周三 16:30-18:00
张昆鹏 HCDG北京核心组代表
HDC2025期间,华为云展示了Serverless与MCP融合创新的解决方案,本期访谈直播,由华为云开发者专家(HCDE)兼华为云开发者社区组织HCDG北京核心组代表张鹏先生主持,华为云PaaS服务产品部 Serverless总监Ewen为大家深度解读华为云Serverless与MCP如何融合构建AI应用全新智能中枢
回顾中 -
关于RISC-V生态发展的思考2025/09/02 周二 17:00-18:00
中国科学院计算技术研究所副所长包云岗教授
中科院包云岗老师将在本次直播中,探讨处理器生态的关键要素及其联系,分享过去几年推动RISC-V生态建设实践过程中的经验与教训。
回顾中 -
一键搞定华为云万级资源,3步轻松管理企业成本2025/09/09 周二 15:00-16:00
阿言 华为云交易产品经理
本直播重点介绍如何一键续费万级资源,3步轻松管理成本,帮助提升日常管理效率!
回顾中
热门标签