32 PITR 与误操作恢复——妙手回春
第 21 章已经证明一条基础备份与连续 WAL 可以在隔离实例中恢复;第 31 章又要求事故 响应先保护现场、明确目标,再授权动作。本章把两者接起来,处理一种尤其危险的情况:
PostgreSQL 没有宕机,复制、监控甚至备份都显示正常,但一笔已经提交的事务把业务 数据改错了。
同步副本会忠实重放错误,HA 切换不会让错误消失;物理 PITR 又会把整个 cluster 带回旧状态,连错误之后的合法写入一起拿走。因此“执行恢复命令”只占很小一部分, 真正的工作是:
本章正式实验故意恢复两个候选。第一个使用默认的 inclusive XID 语义,错误事务被重放, 所以必须否决;第二个使用 exclusive XID,安全事务存在而错误事务不存在,才可作为历史 正确状态。实验随后证明一个更重要的反例:直接切到第二个候选会丢掉目标之后 100 笔合法 写入,只有经过审计对账,最终业务状态才完整。
学习完成标准
完成本章后,读者应能:
- 区分误更新、误删除、误 DDL、批处理越界和外部副作用事故;
- 写出影响对象、错误事务、持续写入、事后合法写与业务真相来源;
- 在逻辑补偿、从恢复副本提取对象、整库 PITR 之间作出有条件的选择;
- 正确比较 time、XID、LSN、name、immediate 与 end-of-WAL 目标;
- 解释
recovery_target_inclusive为什么会决定错误事务是否被保留; - 理解 XID 按事务开始分配而按提交顺序恢复,不能把数字大小当提交顺序;
- 根据 backup lineage 与 timeline history 选择
current、latest或明确 timeline; - 把时区、时钟偏差、日志延迟和事务时间语义写入目标误差预算;
- 使用 Pigsty
pig pitr --plan审阅真实恢复计划,并区分 managed restore 与 side restore; - 在不覆盖原集群、不接入 Patroni、不开放 TCP、不回写 archive 的环境中恢复候选;
- 用 PostgreSQL 日志、recovery 配置、控制信息与 SQL 共同判断恢复进度;
- 以对象 manifest、关键交易和跨表不变量验证数据,而不是只看实例能启动;
- 用条件写入把历史正确值与目标之后的合法增量合并,并在不匹配时整批回滚;
- 隔离 outbox、定时任务、CDC、邮件、支付和 webhook,防止恢复副本制造第二次事故;
- 区分“历史候选正确”“对账完成”“服务可切换”和“生产已批准”;
- 输出一份可复核的 target、backup、WAL、timeline、验证、清理与决策证据包。
这不是“把时间拨回去”
物理 PITR 的输入和输出可以写成:
其中:
- $B$ 是结束于目标之前的某份物理基础备份;
- $W$ 是从该备份一致点开始的连续 WAL;
- $T$ 是恢复目标;
- $\tau$ 是所选 timeline;
- $C$ 是整个 PostgreSQL cluster 在该历史分支上的一致状态。
这个公式没有说 $C$ 就是现在应交付给用户的业务状态。若错误提交点为 $T_e$,当前时刻 为 $T_n$,则还存在两类信息:
exclusive PITR 可以得到 good_before,但不会自动得到 good_after;外部支付、邮件或消息
也不在物理数据目录里。最终状态通常更接近:
这里的 $\oplus$ 不是盲目覆盖,而是带身份、顺序、幂等键和前置状态检查的业务合并。
从事故到交付的七道门
| 决策门 | 必须回答 | 缺失时 |
|---|---|---|
| 事故门 | 哪些对象错、哪笔提交错、错误是否仍继续 | 只保护现场,不恢复 |
| 真相门 | 历史正确值与事后合法事实分别来自哪里 | 升级业务 owner |
| 血缘门 | 哪份 backup 结束于目标前,WAL 是否连续,timeline 是哪条 | 阻断 restore |
| 隔离门 | 是否保留原集群、关闭路由与外部副作用 | 不启动候选 |
| 目标门 | inclusive/exclusive 的可证伪预期是什么 | 至少恢复两个候选 |
| 数据门 | manifest、不变量与副作用对账是否通过 | 不切流 |
| 服务门 | 写围栏、路由、观察窗、回退与 owner 是否齐备 | production gate=pending |
严重度不能替代这些门。即便是 SEV1,也不能因为“时间紧”就跳过 timeline 或外部副作用 判断;即便只错一行,也可能因为已经触发支付而需要跨系统对账。
与第 21 章的分工
| 第 21 章 | 本章 |
|---|---|
| 从损失场景设计备份体系 | 从已发生的误操作界定恢复边界 |
| 证明 full backup + WAL 可恢复 | 证明目标事务能被精确包含或排除 |
| 使用预先创建的 named restore point | 从 source audit 独立取得真实 damage XID |
| 验证 keep 存在、discard 不存在 | 验证 safe、damage、post-target 三类提交 |
| 保留停止后的恢复目录 | 验证后删除两个一次性候选 |
| 不处理事后合法写入 | 实际对账并保留 100 笔合法写 |
两章共同坚持:repository status=ok 不是恢复证明,第一条查询成功也不是恢复完成,
恢复工具成功更不是业务可用。
正式实验与结论边界
参考实验运行于已确认的四节点 Pigsty 开发沙箱:
正式观测:
最终还证明:
这些时间只是 42.4 MB 合成沙箱的一次观测,不能外推生产 RTO。实验没有切业务路由,没有 测试并发交错事务、缺失 WAL、加密密钥丢失、区域故障、真实支付补偿,也没有批准生产 操作。
阅读前后关系
本章目录
32.1 先界定误操作
32.2 恢复目标与时间线
32.3 隔离恢复策略
32.4 执行恢复并观察进度
32.5 数据验证与安全回切
32.6 实战:随机恢复目标演练
权威参考
PostgreSQL:
- Continuous Archiving and Point-in-Time Recovery
- Recovery Target Settings
- Backup Control Functions
- Recovery Information Functions
- Control Data Functions
Pigsty:
上一章:事件分级、现场保护与应急决策——枕戈待旦 · 返回下卷导读 · 下一章:故障切换与集群重建——力挽狂澜 · 查看全书目录 · 查看索引中心