跳至内容

31.6 实战:盲抽症状的桌面演练

本节不对数据库制造故障。它先从 Pigsty FULL/L3 沙箱采集一份最小只读上下文,再从 八个场景中盲抽两个,把本章协议压缩进前十五分钟。这里有两个容易混淆的 “level”:

Pigsty FULL/L3   监控接入层级:PG + node + pool + HA + logs
experiment L0   风险层级:read-only,在线 mutation 为零

参考 run 的响应由程序生成,用来证明合同和 validator 自洽;真正的人员训练必须由主持人 只发盲包、按请求提供证据卡并独立评分。

31.6.1 随机症状、误导性首发告警与缺失信息

先读合同

完整边界见 lab-contract.md,环境与验收条件见 requirements.json,响应协议见 incident-contract.json,拓扑与路由见 topology.mmd,参与者填写 response-template.json

先做纯静态检查:

static/labs/ch31/task.sh lint

完整参考 run 需要连接已经确认的四节点开发沙箱,但在线阶段只有只读 SQL、Patroni REST 和 pgBackRest info

export PG36_EVIDENCE_DIR="$(
  mktemp -d "${TMPDIR:-/tmp}/pg36-ch31.XXXXXX"
)"
export PG36_CH31_SEED=pg36-ch31-reference-v1

static/labs/ch31/task.sh all

也可以分步执行:

static/labs/ch31/task.sh capture
static/labs/ch31/task.sh exercise
static/labs/ch31/task.sh verify
static/labs/ch31/task.sh review

capture 显式使用 BEGIN READ ONLY、短 statement/lock timeout,只保存聚合会话、复制、 slot、archive、control identity 和缩减后的 HA/backup 上下文。它不读取业务行、不保存 query text 或原始日志。exercise 完全离线,不 pause Patroni、不 failover、不重启、不 terminate connection、不改路由、不恢复 backup。

八个场景让首发症状“不够用”

场景首发误导正确主路线
订单数下降、复制延迟为零把同步副本误当历史副本PITR
数据库健康、退款突然增长把技术健康误当语义正确PITR
写端点 503、primary up把接入故障误当 primary 故障HA
DCS timeout、节点自称 primary相信单节点自报角色HA
connection timeout、CPU 43%只看 CPU,忽略连接槽和 poolOVERLOAD
满盘且 replica lag把 lag 当根因,想手删 WALOVERLOAD
checksum mismatch、lag 为零把同步状态当完整性证明INTEGRITY
seq/index 结果不同REFRESH VERSION 当重建INTEGRITY

每个 blind packet 只包含:

  • initial signal 与已报告用户影响;
  • 可以请求的证据卡 ID、问题、层次和时间成本;
  • 十五分钟 deadline 与作答规则。

它不会包含 hidden truth、严重度答案、route、required card、safe/dangerous action 或 证据 observation。facilitator-pack.json 才保存这些内容。场景源文件本身是公开教材, 所以这种隔离是教学流程而非密码学保密;正式考核应由主持人控制文件访问或使用私有 派生场景。

“没有证据”也要进入记录

参与者请求一张暂时不可得的证据卡时,主持人应回答:

unavailable / permission denied / collector down / retention expired

而不是替换成“正常”。参与者要决定是换独立观察面、升级权限 owner、缩小动作,还是 因为关键事实缺失而保持 stop line。事故能力的一部分就是在证据不完整时拒绝不安全的 确定性。

31.6.2 分别按单人和团队模式完成前十五分钟

主持方式

  1. 主持人运行参考工具并单独保管 evidence directory;
  2. 只把一个 blind packet 与空白 response template 发给参与者;
  3. 参与者先声明五轴影响和当前 severity;
  4. 参与者按 ID 请求证据卡,主持人从 facilitator pack 逐张返回 observation;
  5. 每个有副作用的建议都要求 risk、owner、expected、stop、rollback;
  6. 第 15 分钟停止,参与者发布状态更新并完成 handoff;
  7. 最后才揭示 hidden truth、required cards、safe/dangerous actions。

参考 run 固定 seed 抽到:

solo  integrity-collation-index  -> INTEGRITY
team  data-accidental-delete     -> PITR

随机 seed 可改变题目,但 runner 会保证两题属于不同路线。不要重复抽到熟题就假装完成 盲测;应记录 seed、场景使用历史和参与者是否见过答案。

solo 与 team 使用同一张答卷

solo 模式四个 role 都由 solo-oncall 承担,但按时间串行切换;team 模式要求 IC、 operator、scribe、business liaison 是四个不同 actor。两者都必须做到:

required evidence complete minute < route decision minute <= 15
all actions belong to declared safe action set
dangerous_actions_executed = []
decision log starts at minute 0 and ends at minute 15
at least one stakeholder update before or at minute 15
production_authorized = false

团队可以让多个 R0 track 并行,但仍只有一个 operator token;单人不能用“我自己复核过” 冒充独立 R2/R3 review。

一份可复用评分表

项目分值失分例
五轴影响与 severity15把 unknown 写成无影响
现场和恢复能力保护20未围住 writer;建议删除 WAL
跨层证据选择20只看一张 dashboard
技术 route 与目标15severity 直接决定 failover
决策日志与 stop line15动作无预期、回退和结果
角色、升级与沟通10多人同时改;不报 unknown
机密与生产边界5粘贴凭据;宣称已获生产授权

发生以下任一项应直接判定需要重练,不用总分掩盖:

  • 在证明 writer 唯一前 promote;
  • 删除现役 pg_wal
  • 在原始证据上执行覆盖式修复;
  • 未经业务 owner 直接覆盖事后合法写入;
  • 把 facilitator 未提供的信息自行当成事实。

程序生成的 responses.json 只是一份 schema-complete reference,不是答题者成绩。真人 评分要保存自己的 response、主持人发卡时间和讨论录音/记录权限,并由未参与执行的人 复核。

31.6.3 在 Pigsty L3 输出时间线、决策日志、证据包与路由选择

正式参考现场

正式 run 在 pg-test 捕获:

PostgreSQL version              18.4
system identifier              bound to pgBackRest stanza identity
timeline                       11
Patroni                         1 running primary + 2 running replicas
physical replication streams   2, max sent/replay gap 0 bytes
pgBackRest status / backups     0 / 6
SQL transaction                 READ ONLY
raw query / raw log             absent / absent
online mutation                 none

现场的 pg_stat_archiver.failed_count 为 21,但 last failure 在 2026-07-29T18:57:58Z,last archived success 在 2026-07-30T01:36:16Z。这正说明累计失败数不能直接解释成“当前归档故障”。本章不因 看到 21 就 reset 统计或修改 archive;它保留 reset 与时间,交给真实趋势和 backup 证据解释。

“repo 中有 6 份 backup”也不等于恢复通过。本次没有执行 restore,公开结论只写 pgbackrest_status=0 和 backup count;第 21、32 章的恢复证据才回答可恢复性。

私有证据与公开摘要分层

证据目录包含:

preflight-evidence.json
blind-packets.json
facilitator-pack.json
responses.json
exercise-evidence.json
negative-report.json
validation-report.json
public-summary.json
review.txt

目录权限为 0700、文件为 0600。review 拒绝 credential URI、SCRAM verifier、 private key、clear password、raw SQL/log field,并检查 preflight、盲包、答案、 exercise 与 public summary 属于同一 run。

公开参考摘要见 incident-run.json。它只保留环境轮廓、路线、安全 边界与验收计数,不公开 facilitator 答案和 live 细节。

反例验证防止“格式漂亮的伪响应”

正式 validator 要求:

31 declared counterexamples rejected
18 live evidence mutants rejected
12 source files hash-bound

它会拒绝:

  • severity 被允许直接选择 route;
  • blind packet 泄露 hidden truth 或 expected route;
  • required evidence 未齐就决策;
  • solo/team role 语义不成立;
  • action 属于 dangerous set 或晚于 minute 15;
  • decision log 缺 expected/stop/rollback;
  • live capture 不是 READ ONLY、cluster/timeline/topology 不匹配;
  • backup system identifier 不同;
  • source/upstream/evidence hash 被替换;
  • 任何 production gate 被打开。

对同一份私有证据可以重复:

static/labs/ch31/task.sh verify
static/labs/ch31/task.sh review

但修改实验源文件、盲包或 response 后,不能继续复用旧 exercise hash;应开启新 run, 保留旧包作为历史。

本章交付物不是根因报告

合格的第 31 章 handoff 应包括:

severity and five-axis basis
current user/data/recovery impact
authoritative or still-unknown writer/timeline
active fences and automation state
evidence manifest and decision timeline
chosen route and alternatives rejected
first safe action / stop line / owner
next update and escalation requests

参考 run 最终结论是:

read-only-context-and-tabletop-protocol-demonstrated
human_competency_claimed = false
production_ch31_gate = pending

下一章从第一条路线开始:面对已经提交的误删误改,怎样选准恢复目标、在隔离实例完成 PITR,并把历史正确状态与事后合法写入重新合并。


上一节:单人值守与团队响应 · 返回本章目录 · 下一章:PITR 与误操作恢复——妙手回春 · 查看全书目录 · 查看索引中心

最后更新于