备份分两种
一句话总结
**逻辑备份是照片,物理备份 + WAL 是录像。**用照片只能回到“昨晚的状态”,而用录像可以回到“事故发生前 30 秒”。
为什么需要它——先确定两个数字
备份设计不是选择工具,而是要回答关于两个数字的问题。
- RPO(恢复点目标)——最多可以承受丢失多少数据
- RTO(恢复时间目标)——必须在多长时间内恢复服务
如果每天执行一次 pg_dump,那么RPO 就是 24 小时。最坏情况下会丢失整整一天的数据。首先要判断这种损失是否可以接受;如果不能,就需要进行 WAL 归档。
**也不能忘记 RTO。**如果恢复一个 500GB 的转储文件需要 6 小时,那么即使有备份,服务也仍要中断 6 小时。
逻辑备份——pg_dump
pg_dump -Fc -d labdb -f labdb.dump # 커스텀 포맷 (압축·병렬 복원 가능)
pg_restore -d newdb labdb.dump
- 可以跨版本、跨架构迁移——可以把从 16 导出的转储导入 17
- 可以只选择一部分进行恢复——例如只恢复一张表
- 使用
-Fp时可供人直接阅读
但它只是一张拍摄于导出瞬间的照片。从昨晚生成转储到今天下午发生事故之间的状态,没有办法恢复。而且对于大型数据库,导出和恢复都可能耗费数小时。
转储适用于“迁移”和“局部恢复”,不是灾难恢复的主力。
物理备份 + WAL——PITR
PostgreSQL 会先把所有变更写入 WAL(Write-Ahead Log,预写日志)。WAL 的写入先于数据文件。因此,下面这个等式成立。
어느 시점의 데이터 파일 복사본 + 그 뒤의 WAL 전부 = 그 뒤 아무 시점이나
这就是 PITR(Point-In-Time Recovery,时间点恢复)。它需要三个组成部分。
archive_mode = on——把已经写完的 WAL 段复制到安全位置- 基础备份——使用
pg_basebackup获取整个数据目录的副本 - 恢复配置——通过
restore_command重新送入 WAL,并在recovery_target_time指定的时间点停止
archive_command 的规则
archive_command = 'test ! -f /archive/%f && cp %p /archive/%f'
%p——源路径,%f——文件名- 成功时必须返回 0,失败时必须返回非 0 值。如果谎报成功,PostgreSQL 就会删除该 WAL,导致对应区间永远无法恢复
- 使用
test ! -f防止覆盖文件。如果用不同内容覆盖同名文件,恢复过程会悄无声息地损坏
失败后,PostgreSQL 会不断重试,并且不会删除 WAL。如果归档目标已满,pg_wal 会持续增长,最终占满磁盘。如果不监控 pg_stat_archiver.failed_count,问题就会在无人察觉的情况下不断扩大,直至爆发。
恢复步骤
# 1. 베이스 백업을 복사한다 (원본은 건드리지 않는다)
cp -r /backup/base /var/lib/postgresql/restore
# 2. 어디서 멈출지 알려 준다
cat > restore/postgresql.auto.conf <<EOF
restore_command = 'cp /archive/%f %p'
recovery_target_time = '2026-08-21 16:20:41+00'
recovery_target_action = 'promote'
port = 5433
EOF
# 3. 복구 모드로 시작하라는 표시
touch restore/recovery.signal
# 4. 띄운다
pg_ctl -D restore start
存在 recovery.signal 时,PostgreSQL 会以恢复模式启动。它持续重放 WAL,抵达目标时间点后,再按照 recovery_target_action 执行相应操作。
promote——提升为可写实例(默认行为)pause——暂停下来,留出检查时间。如果希望确认后再做决定,选择这一项更安全
恢复时必须遵守的原则
**绝对不要在原始实例上直接恢复。**应当在另一个目录、另一个端口启动并确认结果后,再进行迁移。这样即使目标恢复时间设置错误,仍有回退余地。
**时间线会发生分叉。**恢复完成并提升后,时间线编号会增加 1(00000002...)。从那一刻起,原始实例和恢复实例便拥有不同的历史。如果不了解这一点,之后很容易陷入“WAL 对不上”的排障困境。
常见错误
把备份放在同一块磁盘上。磁盘损坏时,原数据和备份会一起丢失。备份必须存放在另一台设备上,最好位于另一个地点。
**从不演练恢复。**这是最常见、代价也最高的错误。备份任务显示绿色成功,与该备份真的能够恢复,是两回事。如果不定期进行恢复演练,就不能声称自己拥有可用的备份。
**忽略 archive_command 的失败。**如前所述,这会导致磁盘被占满。
**只保留逻辑备份。**这等于接受一天的 RPO,但大多数团队从未明确同意过这一点。
实务中应使用专业工具
实际工作中不会自行编写脚本,而会使用 pgBackRest 或 Barman。这些工具提供增量备份、并行压缩、保留策略、上传到 S3,以及最重要的备份验证。本实验的目的,是了解这些工具在内部究竟做了什么。
用一句话概括就是:
从未实际恢复过的备份,不算备份。