32.4 执行恢复并观察进度
一次 PITR 至少有四个不同的“完成”:
pig pitr --no-restart 成功只证明 pgBackRest restore 阶段完成;pg_ctl -w start 成功
可能只代表 hot standby 已可读;pg_is_in_recovery() = false 证明 recovery 已结束,
仍不证明目标业务状态正确。工具状态必须映射到这条状态机。
32.4.1 从已验证备份克隆恢复目标
冻结一份可重放参数包
执行前把变量写入私有 evidence,而不是临场从 shell history 猜:
秘密只保存引用或受控位置,不复制进 JSON。参数包要能回答“同一份证据能否重放同一个 候选”,但不能变成凭据泄漏包。
先验证 repository 和 target 可达性
只读预检:
检查:
- stanza
status.code = 0; - exact backup label 存在且
error=false; - backup type/dependency 与预期一致;
- backup end 在 target 之前;
- archive 与 timeline history 覆盖 target;
- restore host 有足够空间、正确版本和 extension library;
- candidate root 不存在,端口与 socket path 未占用。
pgbackrest check 成功仍不替代 restore。它验证 repository/stanza 的一组条件,不会运行
本章业务探针。
为 side restore 建一次性目录
本章 runner 只接受形如:
的 exact path。目录必须:
Pig 要求 custom -D 预先存在、归 DBSU 所有;它不会代为创建,因为在 destructive
classification、owner 检查和 plan 输出之前必须先知道具体目标路径。
先 plan,后 execute
inclusive 候选:
审阅 plan 后,在受 guard 约束的自动化中把 --plan 换成 --yes。exclusive 候选只增加:
不要同时改变 backup、timeline、target action 或验证探针,否则两个候选无法归因比较。
Pig 的 first-class 参数负责 target、backup、timeline、data directory 与生命周期;
-- 后的原生 pgBackRest 参数不能绕过这些边界。当前 CLI 在 structured output 下要求
显式 --yes 才执行,--plan 是无执行预览路径
(pig pitr Safety Mechanisms)。
读懂 restore 结果
本章正式 run 的 Pig 结果包括:
patroni_active=true 在这里是好事:它描述 restore host 上原有 live replica 的 Patroni
没有被 side restore 停掉;隔离 candidate 尚未启动。不能把它误读成“候选已由 Patroni
管理”。
文件恢复失败时
若 pgBackRest restore 失败:
- 保留 plan、stdout/stderr、candidate marker 与 repository snapshot;
- 不启动部分恢复目录;
- 判断是 backup、WAL、key、权限、空间、tablespace 还是版本问题;
- 停止任何 exact candidate postmaster;
- 只删除当前 marker 所有的 candidate;
- 修复原因后开启新 run,不覆盖旧 evidence。
managed restore 失败时,Patroni 可能已停止且 PGDATA 可能只恢复了一部分;不能因失败而 直接重启 Patroni。side restore 则不应改变 managed 生命周期,这正是事故调查优先使用 它的原因。
32.4.2 监控 WAL 重放、目标达成与启动状态
手工启动时覆盖危险继承配置
正式 runner 使用 PostgreSQL 18 的 pg_ctl 启动 custom PGDATA,并通过 -o 传入:
以及 source 的五项 recovery-critical maxima。完整、安全转义与路径验证见
exercise.py,不要从上面的概念清单拼接未审阅 shell。
第一条连接可能发生在 recovery 中
若 hot_standby=on,PostgreSQL 达到一致状态后可以开放只读查询,而后继续重放 WAL。
因此:
的 -w 只等待 server ready,不保证 target_action=promote 已完成。第 21 章正式实验
已经实际观察到:
本章 runner 继续轮询:
只有 pg_is_in_recovery() = false 才表示 promote action 已完成。随后仍先运行只读业务
探针;“可写”只是候选能力,不是允许应用写入。
分解恢复时延
用一个总秒数会掩盖瓶颈。本章分开测:
关系:
$$ T_{\text{technical}} = T_{\text{identify}}
- T_{\text{plan}}
- T_{\text{copy}}
- T_{\text{replay}}
- T_{\text{validate}} $$
真实 RTO 还要加:
$$ T_{\text{service}} = T_{\text{technical}}
- T_{\text{reconcile}}
- T_{\text{cutover}}
- T_{\text{application validate}}
- T_{\text{approval}} $$
本章没有执行后三项,所以不会从 2.8 秒 restore 推导“生产 RTO 3 秒”。
监控哪些进度
| 阶段 | 观察 | 正常推进 | 阻断 |
|---|---|---|---|
| 文件 restore | pgBackRest log/result | files restored, exit 0 | missing backup/key/space |
| 启动 | postmaster log、PID、socket | startup then consistent state | config/library/tablespace error |
| archive replay | PostgreSQL log、replay LSN | requested WAL advances | repeated missing/corrupt WAL |
| target | log + target-specific data | stop before/after expected commit | target not reached |
| action | recovery functions | paused/promoted/shutdown as declared | unexpected action |
| validation | SQL manifest | expected safe/bad/post sets | any invariant mismatch |
没有通用的“百分比”能准确表示 archive recovery,因为最终 target 与可用 WAL、restore latency、replay workload 都会影响剩余工作。比虚构 73% 更有用的是保存已请求 WAL、 last replay LSN、目标和时间趋势。
target 未达到就是失败
PostgreSQL 明确规定:配置了 recovery target,但 archive recovery 在到达它之前结束, server 会以 fatal error 停止 (recovery_target_action)。
常见原因:
- 所选 backup 本来就在 target 之后;
- 中间 WAL 缺失或不可读;
- timeline 选错;
- target time/XID/LSN 根本不在该历史;
- repository credential 或网络中断;
- target 格式/时区错误。
禁止把 last replay LSN 当成“近似成功点”继续交付。应回到血缘与 target 证据。
32.4.3 用原生文件、日志和 SQL 复核工具状态
三个观察面互相校验
文件/配置面
现代 PostgreSQL 通过 recovery.signal 进入 targeted recovery;若同时有
standby.signal,standby mode 优先。pgBackRest 会把 recovery 设置写入有效配置,
操作者应读 effective result,不能只看手写模板。
日志面
关注事件顺序,而不是只搜 ready:
日志时间必须与第 32.2 节的时区证据绑定。敏感业务值、凭据和原始查询不应未经筛选进入 公开 evidence。
SQL/控制面
在 promote 后,一些 recovery 函数会返回 NULL 或历史最后值,这是状态语义,不是自动
错误。原始 system identifier 应在私有证据中受保护;公开摘要通常只需要
“matches source lineage=true”。
工具结论必须回到原生事实
| 工具说法 | 原生复核 |
|---|---|
| side restore | effective PGDATA 与 managed PGDATA 不同;Patroni 未停 |
| archive off | SHOW archive_mode |
| target promote | pg_is_in_recovery() = false 与日志 |
| exact timeline | backup/history/config 与 control data |
| no TCP | SHOW listen_addresses + OS socket table |
| candidate stopped | exact postmaster.pid/socket absent |
| backup retained | restore 后再次读取 repository catalog |
平台包装减少操作错误,但不会改变 PostgreSQL 的恢复语义。证据同时保留 Pig structured result 与原生复核,才能在 CLI 版本变化或输出解释争议时继续审计。
pg_waldump 的位置
pg_waldump 可在高级调查中识别 WAL record、事务 commit/abort 与 relation 变化,但:
- 需要匹配 PostgreSQL major;
- 输出是低层内部格式,不是业务审计;
- 应分析受保护副本或 archive 文件;
- 不应在运行中的 active
pg_wal上做会干扰现场的操作; - 结果仍需与日志、catalog 和业务 identity 关联。
本章正式 run 不靠 pg_waldump 猜 XID,而是从同一错误事务写入的 source audit 取目标,
再由两个候选证明包含关系。
候选状态表
恢复完成后先填:
下一节才把 accepted candidate 与当前 source、good-after manifest 和外部系统放在一起, 决定提取、修补或切换。
上一节:隔离恢复策略 · 返回本章目录 · 下一节:数据验证与安全回切 · 查看全书目录 · 查看索引中心