Skip to content

WAL 与崩溃恢复

WAL 原理、LSN、checkpoint、WAL 归档、崩溃恢复流程(与 MySQL 的对比)。

Updated View as Markdown
For humans

WAL 与崩溃恢复

PostgreSQL 用 WAL(Write-Ahead Logging)保证持久性:任何修改先写 WAL 日志,再改数据页。宕机后靠 WAL 重放恢复,已提交的事务不丢失。这和 MySQL 的 redo log 是同一思想,但 PG 只有一套日志,没有 binlog 的对应物(复制和归档都从 WAL 来)。

WAL 的工作方式

先写 WAL 再改数据

关键点:

  • 事务提交时 WAL 必须落盘(synchronous_commit=on),数据页可以留在内存慢慢刷
  • 日志顺序追加,把随机 IO 变顺序 IO
  • WAL 记录有全局递增的 LSN(日志序列号),数据页上记录最近修改它的 LSN,恢复时只重放比页 LSN 新的日志

checkpoint

checkpoint 把 shared buffers 中的脏页刷到磁盘,并推进 redo 起点:恢复时只需要从最近一次 checkpoint 之后的 WAL 开始重放。checkpoint 由 checkpointer 进程周期触发,受 checkpoint_timeoutmax_wal_size 控制。

WAL 文件循环复用,被 checkpoint 覆盖的段可以重用。如果 WAL 生成速度超过 checkpoint 推进,会导致“WAL 堆积”,常见于大事务和长时间未 checkpoint。

崩溃恢复流程

  1. 重启后从最近 checkpoint 的 LSN 开始扫描 WAL
  2. 重放所有比数据页 LSN 新的修改
  3. 已提交但未刷盘的事务恢复,未提交的事务回滚(靠 CLOG 判断提交状态)
  4. 完成后数据库可对外服务

恢复时间取决于 checkpoint 到崩溃点之间的 WAL 量,所以 checkpoint 太稀疏会让恢复变慢。

WAL 归档

archive_command 把 WAL 段复制到归档存储(如 S3)。基础备份 + WAL 归档 = PITR:可以恢复到任意时间点。这是 PG 备份恢复的核心机制,也用于流复制的备库初始化。

与 MySQL 的对比

维度 PostgreSQL MySQL
日志数量 一套 WAL redo + undo + binlog 三套
提交协议 WAL 落盘即提交,无两阶段 redo/binlog 两阶段提交
复制来源 WAL 流式传输或逻辑解码 binlog
回滚机制 旧版本留在堆里等 VACUUM undo log 反向操作

PG 没有 MySQL 的 binlog/redo 一致性难题,因为只有一套日志。逻辑复制从 WAL 解码,不需要第二套日志。

面试追问

  1. WAL 解决什么? 持久性。先写日志再改数据,commit 时日志落盘即可,数据页异步刷。宕机后重放恢复
  2. LSN 是什么? 日志序列号,全局递增。数据页记录最近修改的 LSN,恢复只重放更新的日志
  3. checkpoint 干什么? 刷脏页并推进恢复起点。太频繁刷盘开销大,太稀疏恢复慢且 WAL 堆积
  4. PG 和 MySQL 日志体系的差异? PG 一套 WAL 搞定持久化、复制、归档;MySQL 三套日志还要两阶段提交协调 redo 和 binlog
  5. PITR 怎么实现? 基础备份加持续 WAL 归档,恢复到任意时间点
Navigation

Type to search…

↑↓ navigate↵ selectEsc close