Background Writing

如果后台进程(backend)需要从缓冲区中驱逐一个脏页(dirty page),它必须将这个页面写入磁盘。这种情况是不希望发生的,因为它会导致等待(例如 I/O 阻塞)——更好的方式是在后台异步地执行写入操作。

这一工作部分由 checkpointer 进程完成,但这仍然不够。因此,PostgreSQL 还引入了另一个名为 bgwriter(后台写入进程)的进程,专门用于后台写盘操作。

bgwriter 和驱逐(eviction)使用相同的缓冲区遍历算法,但有两个关键区别:

bgwriter 使用自己独立的时钟指针(clock hand),该指针从不会落后于驱逐的指针,通常还会超过它;
在遍历缓冲区时,bgwriter 不会降低页面的 usage count(使用计数)。
当一个缓冲页未被固定(unpinned)且其 usage count 为 0 时,如果它是脏的,bgwriter 就会将其刷新到磁盘。换句话说,bgwriter 在驱逐操作发生之前运行,主动地将那些很可能即将被驱逐的页面提前写入磁盘。

这样做的好处是:被选中驱逐的缓冲页很可能已经是干净的(clean),从而提高了驱逐操作的效率,避免了后台进程被迫同步写盘的代价。

总结

checkpointer 是“周期性清理工”,而 bgwriter 是“持续扫地工”。

checkpointer 负责最终的数据落盘一致性,而 bgwriter 提前清理“潜在垃圾”,让后台线程少“踩雷”。二者配合,保障了 PostgreSQL 的高并发性能和写入平滑性。

参考书目

  1. Egor Rogov, PostgreSQL 14 Internals, https://postgrespro.com/community/books/internals