35.2 先分类再抢救
“corruption”不是一个恢复方案。至少要区分:存储的字节/页是否错误、从源数据派生的 结构是否错误、业务意义是否错误。检测工具、恢复来源和可接受损失都不同。
35.2.1 物理页、存储与 checksum 错误
物理异常的证据链
典型入口:
checksum mismatch
invalid page / invalid page header
could not read/write block
short read
I/O error / filesystem remount read-only
storage medium error / controller reset
unexpected relation segment size or missing file这些信号仍需定位:
one block / one relation / one tablespace / one device / many hosts
heap / index / toast / catalog / WAL / control
primary only / replica too / backup copy too
read-time detection / write-time failure / recovery-time failurechecksum failure 说明“读出的 data page 与页内 checksum 不一致”,不自动说明是磁盘: 坏内存、DMA/controller、虚拟化、filesystem、软件 bug 或离线篡改都可能改变字节。
交叉副本不能只比较 SQL 行
在相同 system identifier/lineage 下,可比较:
same relation identity and logical object
same or corresponding block/LSN context
primary, replica, backup and storage snapshot
kernel/storage errors on each host物理 replica 可能从 primary 接收已经损坏的逻辑变化,也可能各自发生局部介质损坏; 共享存储/镜像又可能让“多个副本都有同样错误”并不独立。恢复源要有独立故障域与实际 校验,不是名字叫 replica 就可信。
默认路线
preserve corrupt original
verify hardware/storage path
identify last known-good source
restore/reseed a new working copy
validate physical + logical + business state只有在没有健康来源且明确接受损失时,才考虑 best-effort extraction。
35.2.2 索引、排序规则与派生结构错误
派生结构可以重建,但先证明 source
index、materialized view、search vector、rollup 与 cache 都由别的状态生成。典型信号:
amcheck raises B-tree invariant error
same predicate gives seqscan/indexscan different rows
unique index behavior conflicts with expected equality
collation stored version differs from provider actual version
OS/ICU upgrade changes comparison rules
primary and standby use different provider versions先关闭 planner 路径做诊断时,只在 clone 或有界 read-only 查询里进行:
BEGIN READ ONLY;
SET LOCAL enable_indexscan = off;
SET LOCAL enable_indexonlyscan = off;
SET LOCAL enable_bitmapscan = off;
-- bounded invariant query
ROLLBACK;这只能帮助比较,不是修复,也不能保证 seqscan 本身绕过 heap 损坏。
collation 是外部语义依赖
collation object 把 SQL 名称映射到 libc 或 ICU provider。text B-tree 的顺序依赖比较
规则;provider 升级后,旧 index 中 tuple 的物理顺序可能不再满足新比较规则。仅更新
collversion 会消除 mismatch 提示,却不会重新排列已有 index。
因此安全顺序是:
inventory affected collation dependencies
-> verify on clone
-> REINDEX affected indexes/materialized structures
-> validate
-> REFRESH VERSION metadata数据库级 default collation 还会影响更多对象;要从 catalogs 枚举依赖,不能只重建 报错的第一条 index。
派生异常也可能来自 heap
heapallindexed 发现 heap tuple 没有对应 index tuple 时,原因可能是 index 本身,也
可能是 heap/visibility/transaction state 异常。REINDEX 后 amcheck 通过只是一个信号;
还要验证 heap、toast、constraints 和业务 invariants。
35.2.3 逻辑不变量、应用写错与语义损坏
checksum 全绿也可能数据完全错误
UPDATE accounts SET balance = 0;
wrong tenant predicate
duplicate external event applied twice
currency unit conversion error
missing ledger entry
referential rule enforced only in application
out-of-order CDC correctionPostgreSQL 会把这些合法写入按 WAL、checksum 和 replication 正确保存。物理工具不会 知道“余额不应为负”或“订单总额应等于明细”。
业务不变量应提前定义:
-- 结构约束能表达的尽量进入数据库
ALTER TABLE account
ADD CONSTRAINT balance_domain CHECK (balance >= 0);跨行、跨表、跨系统不变量需要 reconciliation:
row count by partition/tenant
sum/count/min/max with known semantic
ledger debit = credit
event id uniqueness and sequence
source-system vs database token
snapshot + change-log continuityMD5/SHA digest 适合证明同一有序投影是否相同,不证明投影本身业务正确;必须绑定 SQL、 排序、NULL/encoding 与 snapshot time。
恢复路线
- 错误发生时间明确且需整体回退:PITR 到隔离实例,再做差异恢复;
- 有审计/事件/ledger:按稳定业务 ID 重放或补偿;
- 上游系统为事实源:重新同步并核对删除/版本;
- 局部错误且可逆:受控 correction transaction;
- 外部副作用已经发生:数据库恢复之外做业务补偿。
不要在原实例上反复 PITR。第 32 章的恢复目标、timeline 与 replay 验证仍适用。
35.2.4 三类问题的恢复来源不同
决策矩阵
| 已证明的异常 | 首选 source | 典型动作 | 核心验收 |
|---|---|---|---|
| heap data page | verified backup/replica/snapshot | restore/reseed new copy | checksum + rows + business |
| index only | verified heap | REINDEX exact dependency | amcheck + query equivalence |
| collation drift | heap + intended provider/version | reindex then refresh | dependency + order + invariants |
| materialized/derived | authoritative base tables/events | rebuild/refresh | source-to-derived reconciliation |
| app wrong write | PITR/audit/event/upstream | recover/diff/compensate | business invariants |
| multiple/unknown | immutable evidence + expert analysis | stop and escalate | missing facts resolved |
分类置信度
不要把一个工具的结果写成绝对结论:
classification: physical-page
confidence: high
supports:
- data_checksums=on
- offline pg_checksums bad=1
- scan raises XX001 on exact heap
contradicts:
- none observed
not_proven:
- root hardware component
- other pages are clean
- backups are independent and usablepg_checksums 找到 1 个坏 checksum,不等于整个集群只有 1 处问题:可能还有未覆盖对象、
业务语义损坏或未来才读出的设备错误。反过来全绿也只覆盖被扫描的 data pages。
停止线
以下任一出现,路线转 STOP_AND_ESCALATE:
- system identifier、timeline 或 binary/PGDATA 归属不明;
- 原始 evidence 已被多次写入,动作时间线无法复原;
- checksum、amcheck、业务结果相互矛盾;
- 所有已知 backup/replica 可能共享故障;
- 唯一副本无法安全克隆;
- 需要
zero_damaged_pages、ignore_invalid_pages或pg_resetwal才能继续; - 数据损失范围涉及监管、财务、隐私或安全事件。
上一节:现场保护与操作边界 · 返回本章目录 · 下一节:页与 checksum 证据 · 查看全书目录 · 查看索引中心