1. 初识WAL:不只是日志,更是数据库的“时光机”
如果你用过PostgreSQL,肯定听说过WAL,也就是预写式日志。但很多人可能觉得它就是个记录操作的日志文件,删了也就删了。其实,WAL远比你想象的重要。你可以把它理解成数据库的“时光机”和“安全气囊”。每次你对数据进行增删改,PostgreSQL并不会立刻把新数据写到真正的数据文件里,而是先把“我要做什么”这个操作指令,原原本本地记录到WAL日志里。等过一会儿,系统比较空闲的时候,再把这些记录批量应用到数据文件上。
这么做有两个天大的好处。第一是崩溃恢复。万一数据库服务器突然断电宕机,内存里没来得及保存的数据就丢了。但别怕,重启后,PostgreSQL会拿出宕机前的WAL日志,像放电影一样,把宕机前所有已提交的事务操作重新执行一遍,数据就神奇地恢复了。第二是数据复制。你想搞个备库做高可用或者读写分离,主库不需要停下来做全量备份,只需要持续地把新产生的WAL日志流式地发送给备库,备库就能几乎实时地跟上主库的进度。
所以,WAL日志是PostgreSQL实现数据持久化和高可用架构的基石。但问题来了,这个“时光机”的记录带(WAL日志)会一直增长,总不能让它占满整个硬盘吧?这就引出了WAL日志的保留与删除机制。简单说,系统需要在“保留足够日志以保证安全”和“及时清理日志以释放空间”之间,找到一个精妙的平衡点。这个平衡点怎么找,就是咱们今天要深入聊的实战内容。我会结合我这些年踩过的坑和优化过的案例,带你从原理到配置,彻底搞懂它。
2. WAL日志的生命周期:何时生,何时死?
要管理好WAL,首先得知道它的一生是如何度过的。一个WAL日志文件(称为一个segment)并不是想删就能删的,它必须经过重重“安检”,确认自己已经完成了所有历史使命,才能被回收或删除。
2.1 删除WAL的五大“通关条件”
PostgreSQL设计得非常严谨,一个WAL文件要想被删除,必须同时满足以下五个条件,缺一不可:
-
崩溃恢复不再需要它:这是最基本的。数据库会定期做检查点(Checkpoint),把内存中的脏数据刷到磁盘。一旦做完检查点,在这个检查点之前的所有WAL记录,对于崩溃恢复来说就已经没用了。因为恢复最多只需要从最近的一个检查点开始重放WAL。所以,早于最后一个检查点的WAL文件就具备了被删除的第一资格。
-
归档任务已经完成(如果开启了归档):很多对数据安全性要求高的场景,比如金融、审计,会开启WAL归档。就是把产生的WAL文件复制到另一个安全的存储位置(比如另一台服务器、对象存储)。如果配置了
archive_mode = on,那么一个WAL文件必须被成功归档后,才能被考虑删除。如果归档命令(archive_command)执行失败,PostgreSQL会一直重试,这个WAL文件就会一直被保留,导致pg_wal目录不断膨胀。我见过太多因为归档脚本写错路径或权限,把磁盘撑爆的案例了。 -
没有活跃的复制槽依赖它:这是流复制的核心。无论是物理流复制还是逻辑复制,备库(或逻辑订阅者)都是通过“复制槽”来告诉主库:“我需要从这个位置开始读取WAL”。每个复制槽都会维护一个
restart_lsn。主库必须保证,任何小于最老的restart_lsn的WAL文件都不能删除,否则备库就断粮了。如果一个备库宕机了很久,它的复制槽又没被清理,主库的WAL就会为了等它而一直保留,这也是WAL暴涨的常见元凶之一。 -
不在
wal_keep_segments的保留窗口内:这个参数是给流复制上的一道“保险”。即使备库暂时断开连接,复制槽还没追上,主库也会强制保留最近N个WAL文件(wal_keep_segments指定数量)。这是为了防止网络闪断导致备库刚重连就发现需要的WAL已经被删了,从而不得不进行耗时耗力的全量重建。在PostgreSQL 13及以后,这个参数被wal_keep_size(以MB为单位)替代,但作用一样。 -
没有被其他进程占用:比如正在用
pg_basebackup做基础备份,或者用pg_rewind重同步备库时,这些工具会读取WAL文件,此时文件也是不能被删除的。
只有闯过这五关,一个WAL文件才算“功德圆满”,可以退场了。
2.2 退场方式:回收与删除
退场也有两种方式,体现了PostgreSQL的优化细节:
- 回收(Recycle):WAL文件被重命名,变成下一个即将被写入的新文件。这避免了频繁创建和销毁文件的开销,提升了性能。
- 删除(Delete):当WAL目录总大小超过
max_wal_size这个软上限,或者回收的文件已经足够多,不需要更多空闲文件时,最老的WAL文件会被直接unlink()(从磁盘删除)。</

1万+

被折叠的 条评论
为什么被折叠?



