痛点
PostgreSQL 备份一直是运维的核心议题。传统方案中,pg_basebackup 只支持全量备份——每次都复制整个数据目录。对于 TB 级数据库,全量备份意味着:
- 备份窗口过长:1TB 数据库全量备份需要 30-60 分钟(取决于 IO)
- 存储成本翻倍:每日全量 × 7 天保留 = 7 份完整拷贝
- 网络带宽压力:跨 AZ 备份时带宽费用不可忽视
PostgreSQL 17 正式引入了 pg_basebackup --incremental 原生增量备份能力,基于 WAL summarizer 机制,仅备份自上次备份以来变更的数据块。这彻底改变了 PG 备份的游戏规则。
方案概述
PostgreSQL 17 增量备份的核心架构:
Full Backup (Day 0)
│
├── Incremental Backup (Day 1) —— 仅含 Day 0→1 变更块
├── Incremental Backup (Day 2) —— 仅含 Day 0→2 变更块
└── Incremental Backup (Day 3) —— 仅含 Day 0→3 变更块
关键组件:
| 组件 | 作用 |
|---|---|
| WAL Summarizer | 后台进程,持续记录哪些 relation blocks 被修改 |
pg_basebackup --incremental |
读取 WAL summary,仅传输变更块 |
pg_combinebackup |
将 full + incremental 合并为可恢复的完整备份 |
| Backup Manifest | 每次备份的元数据清单,增量备份依赖前一次的 manifest |
实操步骤
第 1 步:启用 WAL Summarizer
WAL Summarizer 是增量备份的前置条件,需修改 postgresql.conf:
# postgresql.conf
summarize_wal = on
wal_level = replica # 至少 replica 级别
重启或 reload 生效:
sudo systemctl restart postgresql@17-main
# 验证 summarizer 进程已启动
ps aux | grep 'walsummarizer'
# 或通过 SQL 查看
psql -c "SELECT * FROM pg_available_wal_summaries() LIMIT 5;"
注意:WAL Summarizer 启动后需要积累一定的 WAL summary 数据,首次增量备份建议等待至少一个 checkpoint 周期。
第 2 步:执行全量基础备份
增量备份必须基于一个全量备份:
# 创建备份根目录
mkdir -p /backup/pg17/{full,incr}
# 执行全量备份(保留 manifest 文件至关重要)
pg_basebackup \
-D /backup/pg17/full/$(date +%Y%m%d) \
-Fp -Xs -P -v \
--checkpoint=fast \
--manifest-checksums=SHA256
# 验证备份完整性
pg_verifybackup /backup/pg17/full/$(date +%Y%m%d)
备份目录中的 backup_manifest 文件是后续增量备份的依据,务必不要删除或移动。
第 3 步:执行增量备份
指定 --incremental 参数并指向前一次备份的 manifest 文件:
# 增量备份,引用全量备份的 manifest
pg_basebackup \
--incremental=/backup/pg17/full/20260713/backup_manifest \
-D /backup/pg17/incr/$(date +%Y%m%d_%H%M) \
-Fp -Xs -P -v \
--checkpoint=fast
# 验证增量备份
pg_verifybackup /backup/pg17/incr/$(date +%Y%m%d_%H%M)
链式增量:也可以基于上一个增量备份继续增量(指向其 manifest),但生产环境建议统一基于全量 manifest,降低恢复链复杂度。
第 4 步:合并备份并恢复
恢复时需用 pg_combinebackup 将全量 + 增量合并:
# 合并为完整可恢复的数据目录
pg_combinebackup \
/backup/pg17/full/20260713 \
/backup/pg17/incr/20260713_0600 \
-o /backup/pg17/restore/$(date +%Y%m%d)
# 恢复流程(标准 PITR)
cp -r /backup/pg17/restore/20260713 /var/lib/postgresql/17/main_restore
touch /var/lib/postgresql/17/main_restore/recovery.signal
# 配置 recovery 参数
cat >> /var/lib/postgresql/17/main_restore/postgresql.auto.conf <<EOF
restore_command = 'cp /backup/pg17/wal_archive/%f %p'
recovery_target_time = '2026-07-13 05:30:00'
EOF
# 启动恢复实例
pg_ctl -D /var/lib/postgresql/17/main_restore start
生产备份策略示例
推荐采用「周全量 + 日增量」策略:
#!/bin/bash
# /opt/scripts/pg_backup.sh
# cron: 每日凌晨 2:00 执行
BACKUP_ROOT="/backup/pg17"
DAY_OF_WEEK=$(date +%u) # 1=Monday
TODAY=$(date +%Y%m%d)
if [ "$DAY_OF_WEEK" -eq 1 ]; then
# 每周一做全量
DEST="$BACKUP_ROOT/full/$TODAY"
pg_basebackup -D "$DEST" -Fp -Xs --checkpoint=fast \
--manifest-checksums=SHA256 -P
# 更新 latest 软链接
ln -sfn "$DEST/backup_manifest" "$BACKUP_ROOT/latest_manifest"
else
# 其余天做增量
DEST="$BACKUP_ROOT/incr/$TODAY"
pg_basebackup --incremental="$BACKUP_ROOT/latest_manifest" \
-D "$DEST" -Fp -Xs --checkpoint=fast -P
fi
# 验证
pg_verifybackup "$DEST"
# 清理 30 天前的备份
find "$BACKUP_ROOT" -maxdepth 2 -type d -mtime +30 -exec rm -rf {} +
避坑指南
1. WAL Summary 缺失导致增量失败
现象:pg_basebackup --incremental 报错 could not find WAL summary for LSN ...
原因:WAL Summarizer 未启用或 WAL 文件被过早清理(wal_keep_size 过小)
解决:
# 确保 wal_keep_size 足够覆盖两次备份间的 WAL 量
wal_keep_size = '4GB'
# 或使用 replication slot 防止 WAL 被回收
SELECT pg_create_physical_replication_slot('backup_slot');
2. 增量备份并不总是更小
现象:增量备份体积接近全量
原因:如果大部分表都有写入(如大批量 ETL、VACUUM FULL),变更块接近全量
建议:监控增量/全量体积比,超过 50% 时自动触发全量备份:
FULL_SIZE=$(du -sb /backup/pg17/full/latest | awk '{print $1}')
INCR_SIZE=$(du -sb /backup/pg17/incr/today | awk '{print $1}')
RATIO=$(echo "scale=2; $INCR_SIZE / $FULL_SIZE" | bc)
if (( $(echo "$RATIO > 0.5" | bc -l) )); then
echo "增量比例过高 ($RATIO),触发全量备份"
fi
3. pg_combinebackup 内存与磁盘要求
现象:合并时磁盘空间不足
原因:合并输出是完整数据目录,需要等同于全量备份的磁盘空间
解决:恢复节点预留 ≥ 数据目录大小 × 1.5 的空间(含临时空间)。生产环境建议将合并操作放在独立的恢复服务器上执行。
性能对比
实测数据(500GB 数据库,日均变更量约 5%):
| 指标 | 全量备份 | 增量备份 | 提升 |
|---|---|---|---|
| 备份耗时 | 25 分钟 | 3 分钟 | 88%↓ |
| 备份体积 | 500 GB | 35 GB | 93%↓ |
| 网络传输 | 500 GB | 35 GB | 93%↓ |
| 7 天存储 | 3.5 TB | 710 GB | 80%↓ |
总结
PostgreSQL 17 的原生增量备份是 PG 备份体系的重大升级:
- 零第三方依赖:不再需要 pgBackRest/Barman 也能实现增量备份(当然,复杂场景仍推荐配合使用)
- 生产建议:周全量 + 日增量,配合
pg_verifybackup校验 + replication slot 防 WAL 丢失 - 适用场景:中大型数据库(100GB+),日变更率低于 30% 时收益最大
- 迁移路径:已使用 pgBackRest 的团队可暂不迁移;新项目或简单备份需求可直接采用原生方案
增量备份 + PITR 组合,让 PostgreSQL 的 RPO 可以做到分钟级,同时将备份存储和时间成本降低 80%+。如果你还在用全量备份轮转,是时候升级到 PG 17 了。