PostgreSQL 以固定大小的数据块(Page)存储数据,默认大小为 8 KB。当客户端执行更新或插入操作时,PostgreSQL 并不会立即将变更写入磁盘,而是先将相关数据页加载到共享内存(Shared Buffers)中,在内存中完成修改,并将该页面标记为"脏页"。所谓"脏页",是指内存中的页面版本已经新于磁盘上的对应版本
在向客户端返回操作结果之前,PostgreSQL 会先将变更记录写入预写日志(Write-Ahead Log,WAL),以保证即使数据库发生崩溃也能恢复数据一致性。但实际的数据文件并不会立刻更新,只有在检查点(Checkpoint)触发或后台写进程执行刷新时,脏页才会被写回磁盘
在此之前,脏页会持续累积在内存中,直到通过以下三种机制之一被刷新:
- 后台写进程(Background Writer,BGWriter):一个常驻后台进程,在可用的干净缓冲区数量下降时,持续将脏页写入磁盘
- 检查点进程(Checkpointer):在触发检查点时(如达到 checkpoint_timeout 或 WAL 超过 max_wal_size),将所有脏页刷新到磁盘
- 后端进程(Backend):在紧急情况下(如共享缓冲区几乎全部为脏页),普通后端进程会自行写脏页,可能导致用户查询阻塞
理解并合理控制脏页的刷新时机与方式,是优化 PostgreSQL 性能的关键