陈老师:1415968548 郑老师:2735197625 乐老师:354331153
客服热线:
19941464235 / 19906632509 / 19906733890 / 19905812933(微信同号)

客服微信

云贝教育 | 【技术文章】我不认为PG的DOUBLE BUFFERING是更优秀的解决方案

作者:云贝学院
发布时间:2022-12-30 09:21
浏览量:559

作者:白鳝

原文链接:我不认为PG的DOUBLE BUFFERING是更优秀的解决方案 (qq.com)


关于PG在Shared buffers上的DOUBLE BUFFERING设计,一直是争议极多的。有一些搞PG的朋友认为这是PG充分利用OS CACHE的一种特殊设计,是PG数据库设计中比较优秀的地方。还有一些朋友则认为这是一种过时的设计,与当前数据库技术的发展潮流所相违背的。前些天有几个朋友谈到这个问题,希望我写篇文章表达下我的观点。

以我这些年做数据库优化的经验来看,DOUBLE BUFFERING的设计如果算是一种技术上的进步,在这一点上我一直是不太认同的。众所周知,现在几乎所有的现代数据库产品都是用 AIO/DIO 等方式来访问底层存储系统,只有 PG 目前还通过BUFFER/CACHE 来读取物理文件。随着现代硬件的发展,BUFFERED IO 的劣势越来越显现出来了。如果我们采用直接IO,绕过文件缓冲,那么就可以绕过 BUFFER CACHE 这一层,让数据从文件到内存更为直接,这会大幅提升OS到数据库缓冲的数据交换的吞吐能力,同时,因为DMA等技术的使用,可以让文件IO消耗的CPU资源更少,让系统更为高效。

这对于大型数据库系统来说绝对是十分必要的。PG数据库越来越被用于大型OLTP系统,直接 IO 替代 BUFFERED IO 肯定可以有效增加大型系统的并发 IO 能力。另外一个方面,操作系统是无法充分理解数据库的PAGE访问逻辑的,因此操作系统缓冲的效率比较 shared buffers 而言,要低的多。两个分别由 RDBMS 和 OS 管理的分离的缓冲的效率肯定没有一个独立的数据库缓冲高,这个应该也是广大研发人员的共识。不过这句话成立的前提是数据库缓冲区被设计的十分高效,其 LRU 算法也被设计的十分合理。通过分析 Oracle DB CACHE 的算法的改进,我们也了解到为什么Oracle 的 DB CACHE 能够保持那么高的 DB CACHE 命中率了。

既然使用统一缓冲,消除 DOUBLE BUFFERING 那么重要,那么为什么 PG 还在坚持使用 DOUBLE BUFFERING 呢?这个原因十分复杂,实际上最近这些年里,PG 社区也在这方面做着不断的努力。通过利用 OS 的 AIO 来替代当前 bufmgr.c 中的BUFFERD IO 操作,不过 PG 的 IO 堆栈太长了,在大量的代码中都存在和 buffered io 相关的内容,再加上 PG 的文件结构导致的预读、连续块访问的 IO 合并等问题,要解决这个问题并不容易。在 IO 路径上,不仅仅需要修改 bufmgr.c,在smgr.c,xlog.c,到底层的 md.c,fd.c,甚至 backend 等模块中都有大量IO相关的代码需要修改。这些修改不仅仅是在调用文件 IO 时的函数调用的修改,还涉及到异步IO模式的修改,以及 IO 优化、预读等一系列的问题。因此这部分的修改中左虽然已经进行了数年,但是要出现在正是发布的版本中,依然还需要一定的时间。这也成为PG代码中的XID64之外的又一个老大难的问题。

除此之外,在 shared buffers 的管理上,也需要做相应的优化,否则哪怕底层 IO 改为了AIO,buffer contention 冲突也会让一个大型的统一的数据库缓冲的性能出现问题。比如在Oracle上遇到的buffer busy waits等待,可能会在PG上放大,从而在高并发访问时引发严重的性能问题。

举个最简单的场景,那就是当多个 backend 需要访问相同的一组 PAGE 的时候,PG目前的管理算法上经常会出现 lwlock 等待方面的超时等问题。而 Oracle从9i 开始已经优化了这方面的算法,当多个并发的会话访问相同的 block 的时候,首先为这个BLOC 申请 db cache 的会话会 PIN 住这个 BUFFER HEADER,然后开始加载这个block(当然也包含 IO 合并以及预读,多块读方面的算法优化),其他并发访问相同数据的会话就会等待 “read by another session”,这个等待事件是 Oracle 10g 才开始引入的,在9i中等待的依然是 buffer busy waits,不过reason code(P3)参数是特殊的,从reason code可以缺别处这种特殊的热块冲突类型。

当PG在这方面算法没有做优化之前,就无法区分这种情况,也就无法与AIO配合,达到最低成本的开销。PG 消除 DOUBLE BUFFERING,在技术发展上来说,是必须要做的事情,只不过因为历史欠债还是较多,这方面的改造工作量很大,需要一些时间来完成。一旦PG完成这个改造,将可以充分利用AIO的能力,大幅提升PG数据库读写的能力,从而让PG数据库真正向大型关系型数据库迈出一大步。目前我们有很多数据库企业都是基于PG生态在做研发,我也希望我们的数据库厂商能够在这方面多投入一些研发,为PG社区解决这个难题提供一些中国方案。