花粉津津乐道的完全自主的Guass数据库究竟什么来头
首先我们需要弄清楚openGauss的产品定位,以及它和PostgreSQL的关系,这有助于我们理解openGauss的整个源码体系和结构。openGauss是华为于2020年6月开源的单机版GaussDB,华为决定自主研发GaussDB时为什么选择了PG,而不是其他的开源数据库如MySQL,我们或许可以从GaussDB的发展历程中寻找答案。
GaussDB并非是一个产品,而是一系列产品的统称,目前GaussDB产品线主要包括GaussDB T (OLTP)和GaussDB A (OLAP)。其中GaussDB T的前身是GaussDB 100,是华为从2007年开始在自研内存数据库基础上全面改造而来的一款分布式数据库,此前华为由于在电信计费领域的需求而自主研发了一款内存数据库。GaussDB A的前身是GaussDB 200,是华为从2011年开始基于PostgreSQL 9.2.4自主研发的一款具备多模分析及混合负载能力的大规模并行处理分布式数据库,支持行列混合存储以及线程化,支持高达2048节点的集群规模,提供PB(Petabyte)级数据分析能力、多模分析能力和实时处理能力。
openGauss内核虽然源于PostgreSQL,但华为在开发过程中结合企业级场景需求,通过C++语言(PostgreSQL是用C语言写的)对80+%的数据库内核代码进行了重构,修改和新增了70万行核心代码。着重在整体架构、数据库内核三大引擎 (优化器、执行引擎、存储引擎)、事务、以及鲲鹏芯片等方面做了大量的深度优化。
openGauss在storage目录的变化主要包括:
新增了列存储相关的功能模块如cmgr和cstore,这是openGauss相比PG的一大增强,通过增加列存储使得openGauss能适用于更多的场景;
新增了mot模块,mot模块是openGauss引入的MOT(Memory-Optimized Table)存储引擎,是openGauss数据库最先进的生产级特性,它针对多核和大内存服务器进行了优化,能为事务性工作负载提供更高的性能;
新增了外表功能的相关模块,如dfs和bulkload等;
新增了备机页面修复模块remote;
将replication模块从backend目录移动到storage目录下;
PG11.3版本数据库中共有290个数据库参数,而openGauss目前有500多个数据库参数,每个参数对应一个数据库内核功能,所以可以看到华为对PG的内核做了非常大的改造和增强。
因此openGauss相比于Postgresql是有一定优势的,不过Postgresql本身强大的社区能力,自身也在一直不停的更新版本,目前最新版本已经是PG15。所以不好说openGauss一定比Postgresql好。
目前国内大部分的国产数据库要么是基于MySQL路线开发,要么是基于开发,也有一些是基于openGauss开源社区。做数据库内核开发的技术难度很大,哪怕开发团队对内核架构与机制的制定上出现了丝毫的问题,上线后都极有可能会出现后果严重。有时一旦确定项目无法进行下去,甚至可能需要推倒重来。所以基于一款已经成熟的开源数据库进行自主研发就是一个很好的选择。那为什么选择PG而不是在互联网公司已经得到广泛使用的MySQL,可能是华为在调研分析后看中了PG各方面优秀的特性:
代码质量高:作为学院派的代表,PG的代码简洁、规范、结构清晰,非常适合从源码级进行二次研发。相比之下,修改MySQL的代码会困难很多。
功能完善强大:PG支持的数据类型丰富(多模能力),SQL语法完善(高级SQL特性),查询优化性能强。以JSON支持为例,PG从2012年的9.2版本就已经添加了对JSON数据类型的支持,相比之下Oracle从2014年发布12c才开始支持JSON,而MySQL直到2015年发布5.7.8版本才开始原生支持JSON。以join算法为例,PG几乎支持所有的多表连接算法;以SQL为例,PG支持大多数SQL语法,相比之下MySQL支持较弱;此外PG的查询优化处理能力,例如复杂子查询等都要强于MySQL。
扩展性强:良好的扩展性使得PG非常适合进行二次开发,例如在PG基础架构之上引入MPP框架可以构建分布式数据仓库GreenPlum(MySQL基本不适合做数据仓库);在PG上引入OpenCypher可以构建具备图数据存储和查询能力的多模数据库AgensGraph;在PG架构上通过将数据自动按时间和空间分片可以构建时序数据库Timescale。
GaussDB发展的10年历程说明华为选择PG是一个十分正确的选择。目前PG的用户增长迅速,生态发展的也比MySQL要好,这说明越来越多的公司和开发者都意识到PG的确是一款优秀的开源数据库。其实在早年间,也有一些公司曾在MySQL上进行自主研发,比如阿里巴巴之前在MySQL社区版的基础上做了大量的性能与功能的优化改进,自主研发了AliSQL用于支撑淘宝双十一等业务,但相比PG来说,这样二次研发的成功案例要少很多。
由于PostgreSQL采用C/S(客户机/服务器)模式结构,客户端为前端(Frontend),服务器端为后端(Backend),所以PostgreSQL的backend目录是整个数据库服务的核心代码目录。
openGauss对PG的backend目录进行了功能上的细化分类,将optimizer、executor、storage等高斯内核的核心功能组件移动到新建的gausskernel目录下,其他一些公共功能模块则被移动到新建的common目录下。
openGauss对gausskernel内核部分代码进行了较大的变动,而内核又是数据库最核心最重要的部分,所以我们需要重点关注内核部分的源代码结构。PostgreSQL中的内核代码都在backend目录下,而openGauss的内核代码则主要在gausskernel目录下(从gausskernel的名称就可以看出来)。
openGauss之所以创建gausskernel目录,我想可能有以下几点原因:
1. 创建内核目录彰显了openGauss对于内核的重视,而不是像PG一样将所有的功能模块都放到backend目录下;
2. 突出华为在数据库内核方面所作的重大改进和优化工作;
3. 单独将内核部分代码单独提出来可以方便项目开发和后期代码维护。
openGauss将PG的backend目录的公共功能模块都统一移动到新建的common目录下,这样做的原因可能有两点:
1. openGuass认为这些模块是数据库系统共有的公共组件或者功能模块,比如PG中backend目录下的catalog、lib、libpq等模块;
2. openGuass基本都保留了这些模块的接口和公共函数代码,所以openGauss与现有的PG生态兼容性较好。openGauss仅对这些代码做了适当优化,所以单独创建common目录可以和gausskernel这样修改较大的模块区分开来。
openGuass在优化器目录中的变化主要是将PG中和optimzier同一目录级别的commands和rewrite移动到optimzier目录下,这说明openGauss将命令模块和查询重写模块归为优化器的一部分。
在架构层面PostgreSQL是多进程架构,为了提高并发度,openGauss将其进一步优化成了多线程架构,openGauss属于单进程多线程模型的数据库。
openGauss在gausskernel目录下新建了runtime目录,将PG的executor目录移动到runtime目录下,并且增加了codegen和vecexecutor两个目录。codegen目录中用到了业界流行的开源编译框架LLVM,用于生成高性能的代码来进一步提升性能;vecexecutor目录则包含了向量化执行引擎的相关代码,用于提升SQL引擎的计算性能。
PG流复制有一个痛点就是在一主一从同步模式下,如果备库宕机,主库就会hang住,同步模式不能自动降级。Oracle有最大可用模式,而MySQL有半同步模式。PG中出现此问题时需要依靠第三方工具进行判断和监控,或者使用一主多备的方式来防止备库异常对主库的影响。
openGauss支持了最大可用模式,开启该参数后在主从连接正常的情况下处于同步模式,如果备机断连会立刻切为异步模式,如果备机再次启动会自动连接并切为同步模式。
PG数据库中的xid是一个32位的整型,如果PG数据库运行了很久,会有xid耗尽的问题。PG针对xid耗尽的问题,采取环的方式进行处理,并在vacuum的过程中增加xid冻结处理。
openGauss中将xid由32位改为64位,因此正常情况下xid不可能会耗尽,不过openGauss中针对xid冻结处理的逻辑仍然存在,只是永远不会担心xid耗尽的风险。
PG数据库中每次检查点执行时,会将所有buffer中的脏页刷到磁盘,如果脏页太多可能会一定的性能影响。
openGauss中支持增量检查点的功能,通过enable_incremental_checkpoint参数开启,通过小批量的分阶段的滚筒式进行脏页刷盘,同时更新LSN信息,回收不需要的xlog日志。
由于操作系统数据块是4K,数据库的一个数据块是8K、16K或32K,这样当一个数据库从内存刷到操作系统的过程中可能因为宕机造成坏损坏从而数据库无法启动或恢复。
PG针对此问题采用了全页写Full Page
Write,就是在checkpoint之后每个页面第一次修改时将整个页面的信息写到WAL中,但是这样会导致写放大的问题。MySQL针对此问题是采用双写,在脏块落盘时先把整个块写到共享表空间中并落盘,如果发现坏损坏,从共享表空间中将整个块读取出来进行恢复。不过Oracle针对块损坏的问题并没有采用什么处理,而是依靠ADG等恢复机制进行故障恢复。
openGauss实现了类似MySQL的双写功能,也是在写块的时候把脏页写到共享表空间中,如果发生问题会从双写表空间中找到完整的数据页进行恢复。通过参数enable_double_write并需要开启增量检查点一起使用。
PG默认的密码加密算法是md5,openGauss增强为SHA256,该功能需要配合客户端改造才能兼容。
PG中的xlog日志是在写满后才会分配下一个日志,这样会导致写满一个16M的xlog日志时会有等待,导致PG在做并发写测试的时候性能会有抖动。
openGauss中实现了xlog的预分配,以xlog未写满时就分配下面一个或几个xlog,经压测性能较稳定。
openGauss在每个库下面增加一个dbe_perf性能监控视图,类似MySQL的performance_schema,里面有几百个性能视图,大部分PG里面也有,不过openGauss单独做到一个schema里面方便查看和管理。
openGauss将每个数据库下默认的public schema做了安全增强,默认普通用户没有权限在public下创建对象,需要进行授权。
openGauss支持基于redo的复制、基于数据页的复制以及两种混合复制,通过enable_data_replicate和enable_mix_replication参数进行控制。
openGauss支持列存表,通过cstore_buffers控制列存缓冲区大小,列存表支持压缩。openGauss优化了列存表并发插入性能,解决了插入时一行数据占一个cu造成空间急剧膨胀的问题。通过开启enable_delta_store参数控制列存表的插入使用临时表向主表merge的方式进行,既保证了性能,也解决了膨胀的问题。
openGauss将PG的进程模型改为线程模型,线程池支持上万并发,通过线程池实现session和thread之间的解耦,提高线程利用率,高并发下不会导致线程频繁切换。
PG中查看复制状态的视图在openGauss中被丢弃,无法查询主从Lag信息。
openGauss的编译需要很多依赖,而且版本固定,造成跨平台编译难度很大,平台通用性差。
openGauss不支持并行。
PG的扩展性在于支持插件,openGauss不支持。
没有PG的社区成熟度高。
性能不如原生PG,由于不支持并行,分析类场景也有不足。
页:
[1]