pgBackRest + pg_checksums 的完整容灾链路
适用版本:PostgreSQL 17 / 18
目标:防数据损坏 + 可验证 + 可回滚 + 可恢复到任意时间点(PITR)
一句话总结:
pg_checksums 负责“发现数据坏了”
pgBackRest 负责“把正确数据找回来”
单独使用任何一个,容灾都是不完整的。
| 灾难类型 | pg_checksums | pgBackRest |
|---|---|---|
| 磁盘 silent corruption | ✅ 发现 | ✅ 恢复 |
| RAID / SSD 位翻转 | ✅ | ✅ |
| 文件系统 bug | ✅ | ✅ |
| 人为误删数据 | ❌ | ✅ |
| 误 UPDATE / DELETE | ❌ | ✅(PITR) |
| WAL 丢失 | ❌ | ✅ |
| 主机宕机 | ❌ | ✅ |
👉 两者组合 = PostgreSQL 官方最强数据安全方案
┌────────────┐
│ PostgreSQL │
│ Data Dir │
└─────┬──────┘
│
pg_checksums
│
校验数据页一致性
│
▼
WAL 归档(archive-push)
│
▼
┌────────────┐
│ pgBackRest │
│ Repository │
└────────────┘
│
Full / Diff / Incr
│
▼
任意时间点恢复(PITR)
pg_checksums --show --data-directory=/var/lib/postgresql
输出示例:
Checksums are enabled in cluster
或:
Checksums are disabled in cluster
⚠️ 这是唯一一次破坏性操作,必须停 PostgreSQL
systemctl stop postgresql
pg_checksums --enable --data-directory=/var/lib/postgresql
systemctl start postgresql
- 每个 8KB 数据页都有校验值
- PostgreSQL 读取数据前自动校验
- 一旦发现损坏 -> 直接 ERROR,避免脏数据扩散
pgbackrest --stanza=main stanza-create
这一步会生成:
repo/archive/main/archive.info
repo/backup/main/backup.info
📌 这是 pgBackRest 的“元数据根基”
archive_mode = on
wal_level = replica
archive_command = 'pgbackrest --stanza=main archive-push %p'
SELECT pg_switch_wal();
ls /var/lib/pgbackrest/archive/main/
## 每周一次
pgbackrest --stanza=main backup --type=full
## 每天
pgbackrest --stanza=main backup --type=diff
## 每小时
pgbackrest --stanza=main backup --type=incr
ERROR: invalid page in block 123 of relation base/...
说明:
- 数据页已经损坏
- VACUUM / SELECT 触发了校验失败
此时:
❌ 不要继续写数据
❌ 不要盲目重启
pg_checksums --check --data-directory=/var/lib/postgresql
可以精确定位:
- 哪个 relation
- 哪个 block
- 是否可恢复
systemctl stop postgresql
rm -rf /var/lib/postgresql/*
pgbackrest --stanza=main restore
默认行为:
- 自动恢复最近一次 一致性备份
- 自动回放 WAL
- 校验 checksum + timeline
systemctl start postgresql
例如:
误删数据发生在
2025-12-27 09:15:00
pgbackrest \
--stanza=main restore \
--type=time \
--target="2025-12-27 09:14:59"
| 阶段 | 作用 |
|---|---|
| 备份前 | 确保备份数据是“干净的” |
| 备份时 | pgBackRest 会跳过损坏页并报错 |
| 恢复时 | 自动校验页一致性 |
| 恢复后 | 防止“恢复后才发现坏数据” |
👉 没有 pg_checksums,坏数据可能被“合法备份”
archive_mode = on
full_page_writes = on
wal_log_hints = on
[global]
repo1-retention-full=2
repo1-retention-diff=7
start-fast=y
delta=y
checksum-page=y
pgbackrest --stanza=main check
pg_checksums --check --data-directory=/var/lib/postgresql
pg_checksums 让 PostgreSQL“敢报错”
pgBackRest 让 PostgreSQL“报错后还能活”