PostgreSQL的脏页是什么?
什么是检查点刷脏? 什么是后台刷脏? 什么是用户后端进程刷脏?
什么是double cache? 什么是操作系统刷脏?
为什么要使用大页?
为什么需要SSD?
什么是IO调度策略? 如何配置?
很多问题, 都可以从这篇文章找到答案?
https://stormatics.tech/blogs/what-are-dirty-pages-in-postgresql
PostgreSQL 将数据存储在固定大小的块(页)中,通常为 8 KB。当客户端更新或插入数据时,PostgreSQL 并不会立即将这些更改写入磁盘。相反,它会将受影响的页加载到共享内存(shared buffers)中,在内存中进行修改,并将该页标记为“脏页”。所谓“脏页”,是指内存中的该页版本比磁盘上的副本更新。
在将控制权交还给客户端之前,PostgreSQL 会将此次更改记录到预写日志(Write-Ahead Log,WAL)中,以确保即使数据库崩溃,数据依然具有持久性。然而,实际的表文件并不会被立即更新,直到检查点(checkpoint)或后台写入器(background writer)将脏页刷新到磁盘为止。脏页会在内存中不断累积,直到通过以下三种机制之一被刷新:
更多PG内核原理, 可参考本书:
理解和控制这些脏页的刷新方式与时机,是实现良好 PostgreSQL 性能的关键。
脏页在多个方面影响性能:
后台写入器是一个独立的进程,其任务是通过在后台写入脏页来保持一定数量的干净缓冲区可用。根据官方文档:
关键的 BGWriter 参数(在 postgresql.conf 中配置)包括:

调优策略:如果你在 pg_stat_bgwriter 中观察到后端进程(就是客户端连接到数据库时, 数据库为客户端开启的专用进程)正在写入页面,可增加 bgwriter_lru_maxpages 和 bgwriter_lru_multiplier;如果 BGWriter 造成过多 I/O,则可适当降低这些参数。通过调整 bgwriter_delay 来平衡写入频率和 CPU 使用。
在检查点期间,PostgreSQL 会将所有脏页刷新到磁盘,并在 WAL 中写入一条检查点记录。调优检查点参数有助于分散 I/O 负载:

调优检查点参数有助于管理脏页刷新的 I/O 影响并减少尖峰。增加 checkpoint_timeout 和 checkpoint_completion_target 可以将写入分散到更长时间,而 max_wal_size 控制何时触发自动检查点。
shared_buffers 决定了 PostgreSQL 用于缓存数据和存储脏页的内存量。该值的设置会影响页面在内存中保留的时间以及刷新频率。我们建议在专用服务器上将其设为内存总量的 25% 到 40%,并注意到更大的值可能需要增加 max_wal_size 以分散写入。过小的 shared_buffers 会导致频繁驱逐脏页,引发后端写入;过大的 shared_buffers 可能在检查点时一次性刷新大量页面,造成巨大的 I/O 峰值。合理的 shared_buffers 值配合恰当的 BGWriter 调优,可以最小化后端写入。
自动清理在更新可见性信息或冻结元组时也会生成脏页。应确保 autovacuum 足够频繁地运行以防止表膨胀,但也不要过于激进以免产生不必要的写入。应根据工作负载调整 autovacuum_vacuum_cost_limit 和 autovacuum_vacuum_scale_factor。在 SSD 上,更激进的 autovacuum 可能更有优势。
1. 先测量:使用 pg_stat_bgwriter 监控以下指标:
目标是让 buffers_backend 接近零;该值过高说明 BGWriter 没有跟上节奏。
2. 合理设置 shared_buffers 大小:从内存总量的 25% 开始;根据工作负载进行调整。如果你的工作集主要是读密集型,可使用更大的 shared_buffers;如果写密集型工作负载导致检查点出现巨大 I/O 尖峰,则可适当减小。
3. 调整 BGWriter 参数:
4. 调整检查点行为:
5. 避免后端写入:如果 buffers_backend 持续上升,要么增加 shared_buffers,要么让 BGWriter 更积极。后端写入通常是查询停滞的主要原因。
6. 考虑操作系统调优:
7. 定期回顾性能:每个工作负载都不同。使用监控工具(例如 pg_stat_activity、pg_stat_bgwriter,以及 PostgreSQL 17+ 中的 pg_stat_io)观察调优对后端写入和 I/O 延迟的影响。迭代式地调整参数。
“脏页”只是内存中等待被刷新到磁盘的已修改 PostgreSQL 页面。它们允许 PostgreSQL 批量执行写入操作,并借助预写日志(WAL)保障崩溃安全性。然而,如果脏页处理机制调优不当,可能会导致 I/O 尖峰和查询延迟。通过理解 shared buffers、后台写入器、检查点和 WAL 的工作机制,并仔细调整诸如 bgwriter_delay、bgwriter_lru_maxpages、bgwriter_lru_multiplier、checkpoint_timeout 和 shared_buffers 等参数,你可以在保证数据持久性的同时,实现平稳、可预测的性能表现。
既然文章提到了垃圾回收冻结、大内存机器的操作系统刷脏、SSD等, 那我就再补充一些文章, 有兴趣的小伙伴可参考: