PostgreSQLNotes

第 16 章:WAL

zjc 于 2026-01-16 发布

这是《PostgreSQL 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 WAL(Write-Ahead Logging)先写日志再改数据页,是崩溃恢复、归档备份和流复制的基础。

16.1 基本原理

事务提交
  -> WAL 记录写入 wal_buffers
  -> 按提交策略刷入 WAL 文件
  -> 后台进程逐步刷脏数据页

崩溃后从检查点重放 WAL,把数据库恢复到一致状态。

16.2 核心参数

SHOW wal_level;
SHOW max_wal_size;
SHOW min_wal_size;
SHOW checkpoint_timeout;
SHOW synchronous_commit;
SHOW archive_mode;
SHOW archive_command;
参数 说明
wal_level minimal / replica / logical
max_wal_size 检查点目标上限
checkpoint_timeout 检查点间隔
synchronous_commit 是否等待 WAL 刷盘
archive_mode 是否归档

16.3 检查点

检查点把脏页刷到数据文件,并记录 WAL 恢复起点。

手动:

CHECKPOINT;

查看:

SELECT * FROM pg_stat_bgwriter;

检查点过于频繁会增加 IO;过于稀疏会延长崩溃恢复时间。

16.4 synchronous_commit

语义
on 等待本地 WAL 刷盘
off 异步提交,可能丢最近事务
remote_apply 等待备库回放
remote_write 等待备库写入
local 等待本地刷盘,不等备库

金融核心交易通常保持 on 或 remote_apply;日志类可评估异步,但必须明确丢失窗口。

16.5 WAL 归档

配置:

wal_level = replica
archive_mode = on
archive_command = 'test ! -f /archive/%f && cp %p /archive/%f'

查看:

SELECT * FROM pg_stat_archiver;

归档目录要有容量监控和保留策略,且应存独立存储。

16.6 PITR

基础备份 + 归档 WAL 可做时间点恢复。

配置恢复目标:

restore_command = 'cp /archive/%f %p'
recovery_target_time = '2026-08-25 12:00:00+08'

恢复前要确认:

  1. 备份完整性;
  2. WAL 连续;
  3. 恢复目标时间;
  4. 是否包含时区;
  5. 恢复到新实例验证。

16.7 WAL 大小治理

查看:

SELECT pg_current_wal_lsn();
SELECT pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), '0/0'));

WAL 增长原因:

  1. 大批量写入;
  2. 高频更新;
  3. 索引过多;
  4. 归档失败;
  5. 复制槽保留;
  6. 检查点配置;
  7. 长恢复窗口。

16.8 复制槽

SELECT slot_name, slot_type, active, restart_lsn
FROM pg_replication_slots;

失效复制槽会保留 WAL,导致磁盘被占满。逻辑订阅必须有监控和清理策略。

本章小结

WAL 用顺序日志换取崩溃恢复和复制能力。生产要理解提交策略、检查点、归档、PITR 和复制槽的关系,并持续监控 WAL 生成与保留。

思考题

  1. 为什么先写 WAL 再刷数据页?
  2. synchronous_commit 各级别有什么差异?
  3. 检查点参数如何影响 IO?
  4. 复制槽为什么会占满磁盘?
  5. PITR 需要哪些备份条件?