PostgreSQL Field Guide

备份、恢复与 PITR

按恢复目标选择逻辑或物理备份,并用演练证明可恢复

选择工具

需求工具/方式关键边界
单库、可移植、选择对象pg_dump / pg_restore不包含集群级角色与 tablespace 定义
全集群逻辑对象pg_dumpall --globals-only 配合各库 dump大库恢复慢,需重建索引
整实例快速恢复pg_basebackup 或成熟备份工具版本和平台约束更强
恢复到某一时间点物理基准备份 + 连续 WAL 归档必须持续验证 WAL 完整性

pgBackRest、WAL-G 与 pg_dump 怎么选

方案更适合不足以单独证明
pgBackRest自托管实例的 full/differential/incremental、并行备份、多 repository、WAL 与 PITR目标 RTO 已达标,密钥和所有 WAL 都可用
WAL-G对象存储导向的物理备份与 WAL 工作流repository 保留、删除保护和恢复正确
pg_dump / pg_restore逻辑迁移、选择对象、小规模恢复与跨版本导出连续时间点恢复或整实例低 RTO
云平台备份降低基础设施维护量跨账户、跨区域、平台外恢复和全部扩展可恢复

不要机械套用固定的每日/每周频率。由 RPO、WAL 生成量、恢复带宽、保留策略和实测 RTO 反推 backup cadence,并保留至少一份独立于主数据库权限边界的副本。

逻辑备份

自定义格式支持并行恢复与选择对象:

pg_dump \
  --format=custom \
  --file=commerce-20260802.dump \
  --dbname='postgresql://backup@db.example/commerce'

pg_restore --list commerce-20260802.dump
createdb commerce_restore_test
pg_restore \
  --dbname=commerce_restore_test \
  --jobs=4 \
  --exit-on-error \
  commerce-20260802.dump

pg_dump 在导出期间提供一致快照,但只能备份一个 database。角色等全局对象另行备份:

pg_dumpall --globals-only > globals-20260802.sql

不要把包含密码哈希的 globals 文件放进普通制品库。

物理备份与 PITR

PITR 需要:可用的基准备份、从基准备份起连续完整的 WAL、正确的恢复配置,以及时间线管理。只保存 WAL 不够;只做 base backup 也无法恢复到任意时间点。

归档命令必须只在安全复制成功后返回 0,并避免覆盖已有文件。对象存储通常需要成熟备份工具管理并发、校验、保留和加密,而不是一条未经监控的 shell 命令。

持续告警 archive failure、缺失 WAL、repository 容量和最近一次可恢复时间。删除旧备份前,让工具按依赖关系计算保留链;不要只按文件日期手工删除。

PITR 分步实操

手工恢复到某个时间点的最小流程:

sudo systemctl stop postgresql
# 把基准备份解压到清空的数据目录
tar -xzf /backup/2026-08-01/base.tar.gz -C "$PGDATA"
touch "$PGDATA"/recovery.signal
# postgresql.conf(或 postgresql.auto.conf)
restore_command = 'cp /archive/%f %p'
recovery_target_time = '2026-08-01 14:30:00+08'

启动后实例回放 WAL 到目标点并暂停(默认 recovery_target_action = 'pause')。确认数据后执行 SELECT pg_wal_replay_resume(); 完成恢复。时间线处理同样需要演练:每次完成恢复都会产生新的 timeline,归档必须能跟上。

pgBackRest 配置示例

最小 repository 配置:

# /etc/pgbackrest/pgbackrest.conf
[global]
repo1-path=/var/lib/pgbackrest
# 示例值;保留策略应由 RPO 和存储容量推导
repo1-retention-full=4
repo1-cipher-type=aes-256-cbc
repo1-cipher-pass=<secret>

[main]
pg1-path=/var/lib/postgresql/18/main
sudo -u postgres pgbackrest --stanza=main stanza-create
sudo -u postgres pgbackrest --stanza=main check

sudo -u postgres pgbackrest --stanza=main --type=full backup
sudo -u postgres pgbackrest --stanza=main --type=incr backup
sudo -u postgres pgbackrest --stanza=main info

# 时间点恢复
sudo systemctl stop postgresql
sudo -u postgres pgbackrest --stanza=main \
  --type=time --target='2026-08-01 14:30:00+08' restore
sudo systemctl start postgresql

check 会端到端验证 WAL 归档,每次修改配置后都应运行。保留链、加密密钥和 repository 权限在恢复时必须全部可用——丢失 cipher pass 等于丢失整个 repository。

恢复演练

每次演练都在隔离实例上进行——备用主机或测试机的另一个端口,绝不用生产数据目录:

  1. 把最近一次备份恢复到临时路径,例如 pgbackrest --stanza=main --pg1-path=/tmp/restore-test restore
  2. 用独立端口启动一个临时实例:postgres -D /tmp/restore-test -p 6543
  3. 运行下面的校验查询与冒烟测试。
  4. 确认所需扩展、角色和恢复密钥都可用;单库 dump 不包含集群级角色。
  5. 停止并删除临时实例。

每次演练记录:备份 ID、起止时间、恢复目标、数据库版本、所需密钥、实际 RTO、可恢复到的最新事务时间、校验查询和异常。

验证至少包括:

SELECT count(*) FROM critical_table;
SELECT min(created_at), max(created_at) FROM critical_table;
SELECT conname, convalidated FROM pg_constraint WHERE NOT convalidated;
SELECT indexrelid::regclass, indisvalid FROM pg_index WHERE NOT indisvalid;

再运行应用层只读冒烟测试。行数相同不证明业务关系和权限正确。

副本不是备份

复制会快速复制误删、错误更新和逻辑损坏。备份需要独立保留、删除保护、校验和恢复演练。

Last updated on

On this page