跳至内容

34.6 保留型故障的安全路由

保留型事故的第一原则是:

先证明“谁还需要哪段历史”,再决定是恢复消费者、迁移恢复来源,还是释放这项需要。

一条复制槽、一个 xmin 或一批 WAL 文件本身不是垃圾。它们是恢复、复制、快照或事务 协议的状态。未经 owner 与恢复链确认的“清理”,可能把空间问题变成不可恢复的数据 问题。

34.6.1 XID:检查 backend_xmin、复制槽 xminpg_prepared_xacts

先列出所有可能的 horizon owner

活动 backend:

SELECT pid,
       datname,
       usename,
       application_name,
       state,
       xact_start,
       backend_xid,
       backend_xmin,
       wait_event_type,
       wait_event
FROM pg_stat_activity
WHERE backend_xid IS NOT NULL
   OR backend_xmin IS NOT NULL
ORDER BY xact_start NULLS LAST;

复制槽:

SELECT slot_name,
       slot_type,
       database,
       active,
       xmin,
       catalog_xmin,
       restart_lsn,
       inactive_since,
       invalidation_reason
FROM pg_replication_slots
ORDER BY slot_name;

两阶段事务:

SELECT transaction,
       gid,
       prepared,
       owner,
       database
FROM pg_prepared_xacts
ORDER BY prepared;

再看 database/relation freeze age:

SELECT datname,
       age(datfrozenxid) AS xid_age,
       mxid_age(datminmxid) AS multixact_age
FROM pg_database
ORDER BY xid_age DESC;

这些视图回答的是不同问题:

  • backend_xmin:该 backend 当前快照仍可能看到多老的版本;
  • slot xmin:消费者需要的数据行版本边界;
  • catalog_xmin:逻辑解码需要的 catalog 版本边界;
  • prepared XID:已经 PREPARE TRANSACTION、等待外部决议的事务;
  • datfrozenxid:数据库中尚未冻结事务的保守下界。

不要把最老 PID 自动当成罪魁

一个长 session 未必持有 xmin;一个短暂但 prepared 的事务可能没有 session 却长期 持锁。logical slot 的 catalog_xmin 也可能成为 catalog vacuum 的约束。先把每个边界 映射到:

owner
business or replication purpose
last successful progress
expected outage/retention window
recoverability if released
approved decision maker

处置路线:

保留者安全路线
应用长事务联系 owner,停止新工作,评估 cancel/terminate 与补偿
prepared transaction与 transaction manager/ledger 对账后 commit 或 rollback
logical slot恢复 consumer,或从新起点重建并明确数据缺口
freeze 落后修复 blocker/资源后执行受控 vacuum/freeze
无法识别保持证据,升级,不释放

完整的 XID、freeze 与膨胀处理见第 28 章

34.6.2 WAL 撑盘:检查归档失败、复制槽和未完成备份

pg_wal 大小不是根因

WAL 目录可以因为正常高写入暂时变大,也可以因为保留者不推进持续增长。先记录:

SELECT pg_current_wal_lsn() AS current_lsn,
       pg_wal_lsn_diff(
         pg_current_wal_lsn(),
         '0/0'::pg_lsn
       ) AS absolute_lsn_bytes;

SELECT slot_name,
       slot_type,
       active,
       restart_lsn,
       pg_wal_lsn_diff(
         pg_current_wal_lsn(),
         restart_lsn
       ) AS retained_wal_bytes,
       wal_status,
       safe_wal_size,
       invalidation_reason
FROM pg_replication_slots
ORDER BY retained_wal_bytes DESC NULLS LAST;

SELECT archived_count,
       failed_count,
       last_archived_wal,
       last_archived_time,
       last_failed_wal,
       last_failed_time
FROM pg_stat_archiver;

同时检查:

physical replica receive/replay progress
logical consumer confirmed progress
archive command/repository health
base backup / restore / WAL summarization activity
checkpoint timing
WAL generation rate by workload
filesystem free bytes and inode headroom

pg_stat_archiver.failed_count 是累计量;单次历史失败不证明当前仍坏。需要看最近成功、 最近失败和时间窗增量。slot active=true 也只说明当前有人连接,不说明 restart_lsn 正在推进。

未完成备份也是恢复链的一部分

备份过程可能需要一段 WAL 才能形成一致恢复点。事故中贸然停止备份、删除 staging 或释放 WAL,可能让本来可用的恢复副本失效。记录:

backup run id / start LSN / stop LSN
repository and archive confirmation
base backup progress
restore validation state
current RPO source
alternative healthy backup/replica

若空间即将耗尽,可以同时减少非关键写入,降低 WAL 增长率;这只是争取时间,不是 修复 retention owner。

slot 的有限上限也不是无损方案

max_slot_wal_keep_size 可以限制 checkpoint 时允许 replication slot 保留的 WAL; 超过可用范围时 slot 可能不再可继续使用,wal_status/invalidation_reason 会反映 状态。它是防止磁盘无限增长的风险取舍,不保证 consumer 无损恢复。配置前必须明确:

consumer maximum outage
WAL generation envelope
alert lead time
reseed procedure
accepted data-loss semantics

34.6.3 绝不手工删除 pg_wal;保护现场后转 ch21/ch28/ch35

为什么文件看起来“旧”也不能删

PostgreSQL 自己依据 checkpoint、recovery、归档和复制需要管理 WAL segment。文件名 顺序不能告诉操作者某段是否仍被 crash recovery、standby、backup 或 timeline history 需要。运行中用 rm 删除 pg_wal

  • 不会更新 control/catalog/slot 状态;
  • 可能让当前实例在 crash recovery 时缺日志;
  • 可能让 replica、PITR 或 backup 无法继续;
  • 会破坏最重要的事故证据;
  • 当前进程暂时继续运行,也不能证明下次 restart 可恢复。

正确做法是:

reduce noncritical WAL generation
preserve SQL + filesystem + archive evidence
identify exact retention owner
repair archive/consumer or establish a new recovery source
release only an exact, authorized object through PostgreSQL
verify recovery chain and filesystem headroom

路由到正确章节

  • XID、vacuum、freeze、膨胀:转第 28 章
  • 归档、备份、恢复链:转第 21 章
  • 已发生文件缺失、checksum/页/索引异常:保护现场,转 第 35 章
  • 错删/误写但物理集群健康、需要时间点恢复:结合 第 32 章

每次转交都带:

facts:
  system_identifier_timeline: ...
  current_and_retained_lsn: ...
  owner_consumer: ...
  archive_backup_state: ...
  growth_rate_time_to_full: ...
actions_already_taken: [...]
unknowns: [...]
forbidden_actions:
  - manual delete pg_wal
  - drop unknown slot

34.6.4 本章的一般止血动作不构成保留型修复

常见伪修复

动作可能短期效果为什么没修复保留边界
cancel 普通慢查询降低 CPU/I/O不一定命中持 xmin 的事务
限制新连接减少 flowslot/归档边界仍不推进
增加磁盘延后满盘owner 与恢复链仍旧失效
重启数据库清部分 sessionprepared xact/slot/归档问题仍在,且增加恢复风险
drop 所有 inactive slot快速释放 WAL破坏未知 consumer 的恢复能力
删除 WAL 文件目录变小数据库状态未修复,恢复链被破坏

增加磁盘在硬故障逼近时可以是合法的时间购买动作,但报告必须写:

temporary headroom gained
new estimated time to full
retention owner unchanged
permanent repair owner/deadline
rollback or capacity reconciliation

保留型成功标准

不是“磁盘百分比下降”,而是:

exact retention owner identified
oldest required horizon is advancing or deliberately re-established
consumer/archive/backup has a valid recovery path
released capability and accepted loss are recorded
WAL/XID growth rate returns inside envelope
replicas and PITR validation pass
temporary storage/traffic controls are reconciled

如果唯一能说的是“删完之后 PostgreSQL 还在运行”,事故尚未被安全恢复。


上一节:流量型止血动作 · 返回本章目录 · 下一节:平台级流量控制与证据 · 查看全书目录 · 查看索引中心

最后更新于