内容提要
本文用银行账本比喻Postgres的WAL:数据文件是余额,WAL是流水账,所有写入必须先记WAL。检查点后旧WAL段可回收,但启用归档后须先归档。备份恢复依赖连续WAL,缺失会导致数据静默丢失。切勿将archive_command设为/bin/true或删除WAL,应修复归档目标并监控pg_stat_archiver。
延伸解读
WAL 不是日志,是数据库的账本
文章用银行账本比喻 Postgres 的 WAL:数据文件是余额,WAL 是流水账。所有写入必须先记 WAL,再更新数据文件。如果只看到 pg_wal 目录占用空间就随意删除,相当于撕掉账本中间几页,后续数据将无法审计。Postgres 10 将 pg_xlog 改名为 pg_wal,正是为了避免用户误以为这些文件无关紧要而手动删除,导致不可恢复的数据丢失。
归档失败时,切勿用 /bin/true 绕过
当 archive_command 失败时,WAL 段会堆积在 pg_wal 中。有人建议将 archive_command 设为 /bin/true 来快速清空,但这会永久丢失这些 WAL 段,破坏备份恢复所需的连续链。正确做法是修复归档目标,或临时将段复制到其他位置(如 cp %p /emergency/mount/path/%f),并监控 pg_stat_archiver 中的 failed_count 和 last_archived_time,及时告警。
缺失 WAL 段会导致静默数据丢失
文章演示了丢失一个归档 WAL 段(如 00000001000000000000000E)的后果:若未指定恢复目标,Postgres 会重放直到 restore_command 找不到文件,然后提升并接受写入,看起来一切正常,但实际丢失了该段之后的所有事务。示例中 5001 条记录只剩 2001 条,余额从 -2866.29 变为 -5179.92。因此必须确保归档 WAL 的连续性,并监控归档状态。
WAL 保留策略由备份管理系统决定
WAL 段是备份之间不间断的链条。当备份过期时,可以安全删除指向下一个备份之前的 WAL 文件,因为没有地方再应用它们。pgBackRest 和 Barman 等备份管理工具提供保留策略配置,可自动清理旧备份及相关 WAL。但文章建议保留多个备份集以确保数据可恢复,不要过早丢弃 WAL。
Q&A
Postgres的WAL是什么?为什么它如此重要?
WAL(Write-Ahead Log)是Postgres的预写式日志,所有对数据文件的修改必须先写入WAL并刷新到永久存储,之后数据文件才会更新。它是ACID中持久性(Durability)的保障,也是崩溃恢复和备份恢复的基础。
为什么不能把archive_command设置为/bin/true来清理WAL?
将archive_command设为/bin/true会让Postgres误以为WAL段已成功归档,从而回收或删除它们,但实际上这些段并未被保存。这会破坏WAL文件的连续性,导致备份恢复时出现无法弥补的缺口,造成数据静默丢失。
Postgres的检查点(checkpoint)如何影响WAL文件的回收?
检查点完成后,数据文件已包含该点之前所有WAL记录的内容,因此崩溃恢复只需从最后一个检查点开始的WAL。此时,检查点之前的WAL段可以被回收(重命名重用)或删除,从而防止WAL目录无限增长。
如果归档命令失败,WAL段会怎样?应该如何处理?
归档命令失败时,Postgres会保留WAL段并定期重试,导致pg_wal目录不断增长。正确的做法是修复归档目标(如网络、存储问题),而不是丢弃WAL。可以临时将段移动到应急位置(如cp %p /emergency/mount/path/%f),并监控pg_stat_archiver视图。
如何监控Postgres的WAL归档状态?
可以查询pg_stat_archiver视图,关注failed_count、last_failed_time、last_archived_time等字段,并检查pg_ls_archive_statusdir()中.ready文件的数量。同时监控pg_wal卷的使用量,设置告警(如80%),并留意服务器日志。
什么时候可以安全地删除旧的WAL文件?
当备份管理工具(如pgBackRest、Barman)根据保留策略决定过期某个备份时,可以删除该备份到下一个备份之间不再需要的WAL文件。但建议保留多个备份集以确保数据可恢复。