聊聊postgresql的double buffering 问题

来源:这里教程网 时间:2026-03-14 21:17:28 作者:

最近有朋友和我们交流 PostgreSQL运维的问题,其中交流提纲里提到了关于Double   Buffering的问题。对于以往习惯于使用Oracle数据库的人来说,不会体会到Double   Buffering这个词的含义。很多Oracle  DBA 也认为 Oracle天生就不需要考虑Double   Buffering的问题的,只有P G/MYSQL 这样的开源数据库才需要关心。事实上, Oracle也就是最近这十几年才彻底的解决了Double   Buffering问题,采用完全绕过文件缓冲区的方法的,在我早期使用的Oracle版本中,如何利用文件缓冲提升大数据量的访问性能还是Oracle   D BA 能够用来挣钱的独门绝技,我也曾利用这个技能帮助用户做过一些优化项目。既然今天要讨论 Double Buffering ,那么我们就先用 P G 的一个 IO 分层结构图来理解一下 P G 的这个问题吧。   我们看到最上面的 s hared buffer P G 的主 B UFFER P G 数据库使用 b ufferd io O S 的文件系统进行交互,因此 P G 数据库的读写都需要使用 O S CACHE 作为缓冲,读取的数据可以通过 O S CACHE 来进行加速,写入的数据先写入 OS CACHE 中,然后再通过 f sync() 来强制刷盘。在 P G 数据库里,我们要访问一个数据块可能会经过两个 C ACHE ,一个是 PG 自己的 S HARED BUFFER S,一个是O S CACHE ,这就是 Double  Buffering 的含义。 Double   Buffering有什么缺点呢?首先是增加了一个数据块访问的路径,数据块要先读入O S CACHE ,然后才能到达 S HARED BUFFERS ,而这个 PAGE Shared   Buffers中被多次使用,期间不再需要再次从文件中读取,因此O S CACHE 中的缓冲的效率其实并不高,甚至可能会产生负面的作用。对于 P AGE 的写入也是如此,你不知道 P AGE 是写入文件了还是仍然存在于 O S CACHE 中,有时候我们必须通过 f sync() 来强制同步 O S CACHE 与文件系统。这种 Double  Buffering 确实增加了 P G 数据库在 cache管理上的复杂性。 实际上, P G 数据库是能从 O S CACHE 上大大受益的,特别是写 I O ,写入 O S CACHE 的延时要远远低于直接写入文件系统。而对于一些访问十分频繁的热表, O S CACHE 也是能够明显的提升 I O 性能的。而交给 D BA 的最为主要的问题是,我们如何管理好这个 Double  Buffering 的环境。这种管理确实比 Oracle这样的使用O _DIRECT 访问的数据库要复杂的多,在 Oracle数据库管理方面,我们只需要设置一个足够大的 sga_target 甚至 Memory_target基本上就万事大吉了。而在P G 数据库的缓冲区管理中,我们还必须考虑如何平衡 Shared   Buffers和O S CACHE P G 的官方文档中,建议 P G 数据库的 Shared   Buffers设置为物理内存的25%左右而不要设置的过高,这个建议主要还是为了平衡O S CACHE Shared   Buffers,让O S CACHE 作为主缓冲, Shared Buffers 作为副缓冲。对于一些不是很大的 P G 数据库,特别是服务器的内存不是很大的数据库系统来说,这是一个较为稳妥的设置方案。可以最大幅度的避免 O S 换页带来的更大的性能问题。因此也有很多 P G   DBA 认为 s hared buffers 不宜设置过大,过大的 Shared   Buffers对P G 数据库性能提升没有多大帮助。不过有很多用户用自身的体验驳斥了这种观点。通过加大 Shared   Buffers,提高Cache   Buffer的命中率,获得了较好的数据库性能。有的D BA 把超过 75%的物理内存使用到Shared   Buffers上,也获得了良好的使用效果。这种模式实际上是把Shared   Buffers作为主缓冲,O S CACHE 作为副缓冲。对于可以把应用中的绝大多数数据放到 Shared   Buffers里而不会产生O S 的换页的运行场景,这种设置是十分有效的。 到时间来说说我们的观点了,对于 P G Double   Buffering,网上的很多观点都有些偏颇,可能持这些观点的人面对的都是自己的系统,并没有关注过不同负载的数据库的需求。因此如果从一个较为全面的角度来说,在现阶段,P G 内核还要依赖于 O S CACHE 来提升 P G 性能的前提下, Double   Buffering依然是目前我们无法绕过去的问题。而对于大多数小系统来说,Double   Buffering并不会给我们带来太大的烦恼,只要确保O S 不换页, Doube   Buffering的副作用是有限的,我们甚至可以完全忽视的。而对于大系统来说,设置多大的Sahred   Buffers是我们需要去面对的头疼的问题,因为面对不同的应用负载,不同的个性化的系统,并没有一个十分明确的优化建议。不像我们在管理Oracle数据库那样,只需要确保物理内存足够,O S 不换页的情况下,尽可能提高 D B CACHE 的命中率就可以了。在 P G 数据库中, 90%的 db ca che命中率不一定比80%的d b cache 命中率有更好的运行性能,因为有可能有我们看到的 90%的物理 IO 实际上是从 O S CACHE 中读取数据的。 基于 Double  buffering 的问题, DBA 需要根据自己维护的数据库系统,通过个性化的优化策略来评估 D B CACHE O S CACHE 对系统带来的性能提升,才能更加正确的设置相关参数,让数据库体验的效果更好。对于大型的 P G 数据库系统,这一点尤为重要。实际上这对于 D BA 来说是一个福音,问题出现了,特别是不容易解决的问题出现了,那么体现 D BA 价值的机会就来了。就像老白当年调整 O S CACHE/BUFFER 为客户提升应用性能一样,这种服务都是客户愿意花钱来获得的。 实际上,解决 P G 数据库的 Double  buffering 问题也并不是像想象的那么困难。注意好几点,大部分系统的这个问题都可以得以解决。首先,不要相信只能使用 25%物理内存作为Shared   Buffers这种固化的经验,因为每个系统都是个性化的,提高D B CACHE 的命中率在绝大多数场景下都是有价值的。其次,需要针对 O S V M 参数做更为精细的调整,包括脏块刷新的策略,这方面我在以前的好几篇文章里都做过阐述,这里就不重复讨论了,有兴趣的朋友可以去读读这些文章。最后, P G 数据库实际上有很多解决这方面问题的插件,可以帮助我们提升 O S CACHE 的效率,比如针对性的进行 O S CACHE / SHARED BUFFERS 的预热等,在某些比较大型的数据库系统,比较复杂的应用场景下,这种预热十分有效。有兴趣的朋友可以去研究一下 pgfincore 这个开源插件,应该会有一些收获的。

相关推荐