跳至内容
35 数据抢救与工程取证——起死回生

第 35 章 数据抢救与工程取证——起死回生

当数据库报告 checksum failure、invalid page、索引不一致或 collation version mismatch, 目标不再是“让错误消失”,而是回答四个必须分开的问题:

detect
  哪个对象、块或不变量出现异常?检测覆盖什么、没有覆盖什么?

preserve
  哪份是原始证据,哪份是可信恢复来源,怎样证明它们没有被改写?

recover
  应重建派生对象、从健康来源恢复,还是只能分段抽取可读数据?

validate
  数据库能启动之外,业务不变量、恢复链与故障域是否重新可信?

“起死回生”不是在唯一副本上尝试越来越危险的参数。专业抢救的第一动作通常是停止 新增写入、保存原始现场、制作可重复的操作副本,并让每次尝试都从同一个证据点分叉。

学习完成标准

完成本章后,读者应能:

  1. 区分物理页/存储异常、索引/排序规则派生异常与业务语义损坏;
  2. 解释 detection、repair、extraction、rebuild 为什么是四种不同工作;
  3. 为停写、只读、storage snapshot、PostgreSQL backup 与 clone 写出一致性边界;
  4. 用 SHA-256、只读介质、操作日志和副本树维护工程级 chain of custody;
  5. 记录 system identifier、timeline、版本、extension、locale/ICU、硬件与最近变更;
  6. 解释 data checksum 保护的是 data page,不覆盖 temp file、所有内部结构或业务语义;
  7. 正确使用 SHOW data_checksums 与离线 pg_checksums --check
  8. 用日志中的 relation/block 线索和 pg_relation_filepath 定位对象,但不手改文件;
  9. 判断存储、内存、内核或文件系统仍不可信时,应先修基础设施;
  10. 区分 bt_index_checkbt_index_parent_checkheapallindexedverify_heapam
  11. 评估 amcheck 的锁、I/O、CPU、内存、隐私与 hot-standby 限制;
  12. 识别 collation provider/version drift,并按“重建依赖对象后刷新版本”处置;
  13. 解释“索引可重建”为什么不能证明 heap 与业务数据安全;
  14. 按备份、健康副本、逻辑来源、分段抽取的优先级选择恢复源;
  15. ignore_checksum_failurezero_damaged_pagesignore_invalid_pagespg_resetwal 限定为克隆现场的最后手段;
  16. 写出停止自救、升级厂商/文件系统/硬件/数据库专业支持的触发线;
  17. 区分“能启动、能查询、结构一致、业务可信、可恢复”五个验收层次;
  18. 为不可恢复范围、估计方法、法律/合规通知和客户沟通保留证据;
  19. 在盲测中区分 1-bit heap page 异常与 collation-derived mismatch;
  20. reset:host 当作需独立审批的 L3 重建风险类别,而不是普通维护命令。

三类损坏,三种恢复来源

类别典型证据主要恢复来源不应默认做
物理checksum、invalid page、I/O error、块读取失败可信 backup、健康副本、存储 snapshot、可读抽取原地改页、删文件、忽略错误继续写
派生amcheck、collation version、错误索引结果heap/源表 + 正确规则重建把 REINDEX 当作 heap 已安全
语义约束外不变量、ledger/事件/业务对账PITR、审计日志、上游事实、补偿用物理工具“修”业务写错

分类可以重叠。一次坏内存写可能同时损坏 heap 和 index;错误 ICU 版本可能让结构在 不同节点上被不同比较规则解释;应用误写也可能生成完全合法的 page/checksum。遇到 冲突证据应扩大范围,不要强选最便宜的修法。

信任阶梯

process started
  < SQL endpoint responds
  < physical/structural checks pass
  < relational and business invariants pass
  < replica/archive/backup lineage passes
  < observation window remains clean

每一层只能证明自己的命题。pg_ctl start 成功不能证明索引返回正确结果; pg_checksums 全绿不能证明 collation、约束外余额或外部副作用正确; 业务抽样正确也不能证明每个 relation block 都可读。

正式实验

本章对 managed pg-test 只做 before/after L0 read-only capture。真实 fault 全部在 pg-test-3 的一次性 PostgreSQL 18.4 中:

/tmp/pg36-ch35-forensics-<run-id>
private Unix socket
data_checksums=on
12,000-row deterministic fixture
stopped known-good snapshot
separate case and working copies

runner 随机安排两个 blind case,正式顺序为:

COLLATION_METADATA -> PHYSICAL_HEAP_PAGE

第一例只在 disposable catalog 中把 exact ICU collation stored version 从 153.121 改为 run-specific fake value:

offline bad checksums        0
amcheck structural pass   true
version mismatch          true
route       REINDEX_AND_REFRESH_COLLATION
repair order  REINDEX -> REFRESH VERSION
repair elapsed            267.719 ms
business invariants match true

它模拟的是版本元数据不一致,不冒充真实 ICU 排序语义升级。

第二例在 stopped clone 上只翻转 heap block 2 中一个 byte:

bytes changed                 1
offline bad checksums         1
online sequential scan    XX001
route       RESTORE_FROM_KNOWN_GOOD_COPY
in-place repair           false
recovered bad checksums       0
business invariants match true

两个 mutated original case 在各自恢复期间保持逐文件 digest 不变,known-good snapshot 也保持不变;最后停止所有临时 postmaster 并删除 exact root。managed PGDATA、服务、 路由、Patroni/DCS 和 reset:host 均未触碰。

验证器构造并拒绝 35 个真实 mutant,包括打开生产/managed 边界、弱化 checksum 阈值、 blind evidence 泄露答案、原地修复、REFRESH 先于 REINDEX、业务 digest 漂移和谎报 清理成功。公开证据见 rescue-run.json

本章边界

正式实验没有:

  • 注入真实磁盘、控制器、内存、内核或文件系统故障;
  • 模拟真实 ICU/libc 比较语义改变;
  • 在唯一副本或 managed PGDATA 上改一个字节;
  • 使用 ignore_checksum_failurezero_damaged_pagespg_resetwal
  • 执行 Pigsty host 移除、重装或生产恢复。

因此它证明的是机制与证据链,不是生产数据可恢复比例或 host rebuild RTO。最终门禁 保持 production_ch35_gate=pending

所属位置

本章目录

35.1 现场保护与操作边界

35.2 先分类再抢救

35.3 页与 checksum 证据

35.4 索引、collation 与 amcheck

35.5 抽取、跳过与重建策略

35.6 工程取证与业务验证

35.7 实战:在克隆环境分类并恢复

权威参考

PostgreSQL:

Pigsty:


上一章:过载保护与资源故障判型——李代桃僵 · 返回下卷导读 · 下一章:事故复盘、控制固化与平台演进——举一反三 · 查看全书目录 · 查看索引中心

最后更新于