跳至内容

36.3 证据质量与决策复盘

复盘拥有响应时没有的时间、权限和上下文,因此最容易犯 hindsight bias:把后来才知道 的答案投射给当时的人。决策质量必须按当时可用信息评估,结果质量则按后来完整 证据评估。

36.3.1 哪些事实当时可见,哪些后来才知道

建 knowledge timeline

普通 timeline 记录系统事件;knowledge timeline 记录响应者何时获得什么信息:

knowledge_id: K-...
observed_at: ...
available_to_roles: [...]
statement: ...
kind: observation | inference | report
source:
  system: ...
  object_identity: ...
  query_or_artifact_hash: ...
quality:
  directness: direct | derived | hearsay
  completeness: ...
  clock_uncertainty_ms: ...
interpretation_at_the_time: ...
decision_ids_informed: [...]
later_evidence: ...
correction: ...

后来发现原告警是 replica、不是 primary,不要覆盖旧记录。追加:

T1 observed: endpoint E reports recovery=true
T1 inference: E is believed to be current primary
T2 correction: inventory and DCS show E was a replica

这样才能问:“在 T1,接受写流量是否合理?”而不是用 T2 的答案责怪 T1。

四栏复盘表

当时可见事实当时假设后来证据当前结论
client timeout 上升primary 过载proxy backend errors + DB 正常故障在 route
WAL 目录增长WAL 生成太快slot restart LSN 不动retention owner 阻塞
新节点可写failover 成功旧主仍可接受直连authority 尚未安全
checksum clean数据无损坏业务 digest 漂移page 完整性与语义不同

要求每个结论能回指源证据,并明确 source identity。截图可帮助人理解,但通常缺查询、 时间窗、变量、完整返回和 hash;关键结论保留机器可读原始投影。

决策日志与复盘文档分离

响应期间的 decision record 应 append-only:

decision_id: D-...
at: ...
objective: ...
known_evidence: [K-...]
hypotheses_considered: [...]
chosen_action:
expected_observation:
stop_condition:
rollback:
authority:

复盘可以评价该决定,却不能重写当时输入。若事故中没有决策日志,这本身就是一个证据 缺口;不要靠会后记忆补成精确逐分钟事实。访谈内容标记为 recollection,并与日志、 审计、metric 和 trace 交叉验证。

证据保真与最小披露

raw evidence 可能包含 query text、角色、IP、token、客户标识或 payload。采用两层:

restricted original
  immutable/retained/access-audited

review projection
  redacted, source-bound, sufficient for the claim

去敏不应破坏关联键;可用 stable pseudonymous token、区间、计数与 hash。复盘仓库只放 projection 和原件位置/权限,不复制 secret 或个人数据。

36.3.2 哪些假设被验证,哪些动作靠运气

好结果不能证明好决策

四种组合都值得复盘:

决策过程结果判断
证据充分、边界清楚成功机制候选,仍需复验
证据充分、边界清楚失败模型或实现有缺口
猜测、无 stop/rollback成功near miss / luck
猜测、无 stop/rollback失败显性事故

“重启后好了”只证明重启与恢复同时发生。它可能清掉等待队列、终止事务、触发 failover、 刷新 cache 或碰巧等到下游恢复;没有前后证据就无法选出机制,也无法知道丢了什么。

为每个关键动作做机制审计

preconditions
  执行前必须为真的事实是否被验证?

scope
  作用到 exact object/session/node/cluster 吗?

mechanism
  为什么它应改变目标症状?

expected
  多久、在哪个观察面看到什么?

stop / rollback
  哪个信号表明应停止或撤回?

result
  预期与实际是否一致?

repeatability
  在隔离环境重演后仍成立吗?

例如取消 exact application_name 会话后 lock waiters 清零,可以支持“这些 fixture session 构成 flow pressure”;它不能证明任意高连接事故都应取消会话。又如从 known-good snapshot 恢复后业务 digest 匹配,支持该 fixture 恢复路线;它不能证明 生产 backup 覆盖同一范围。

验证假设,而不是验证故事

每个 hypothesis 写:

hypothesis: H-...
prediction:
  if_true: ...
  if_false: ...
test:
  isolation: ...
  changed_variable: ...
  independent_observations: [...]
result:
alternative_explanations:
status: supported | weakened | rejected | unresolved

如果测试同时改变配置、版本、流量和拓扑,即使问题消失也无法归因。生产不能安全复现 时,在 clone、replay、模型或历史数据上验证,并把外推边界写清。

near miss 也进入控制系统

这些情况值得和事故一样记录:

  • 错命令被 safeguard 阻止;
  • 误切换前发现 system identifier 不符;
  • dangerous parameter 在唯一副本执行前被 review 拒绝;
  • restore candidate 偶然正确,但 target 没有审计来源;
  • unknown request outcome 恰好没有重复副作用。

near miss 提供了低损失的失效路径证据。若只统计造成用户影响的事件,平台会忽略已经 穿透多层防线、仅靠最后运气没有出事的路径。

36.3.3 告警、日志和时间同步缺口

从问题反推 observation contract

不要以“多收日志”为默认行动。先列事故中无法及时回答的问题:

问题所需信号identity/维度retention
谁受影响user SLI / request outcomeservice、operation、segment至少覆盖 SLO 窗口
查询为何慢wait、plan、query ID、I/Ocluster、db、role、query覆盖发布与周期负载
谁保留 WALslot/subscriber/archivesystem id、timeline、slot owner覆盖恢复窗口
谁拥有写权威DCS、Patroni、timeline、routecluster/member/endpoint覆盖 failover 前后
数据何时变化audit/WAL/business eventtransaction/token/object由 RPO、合规决定
恢复是否可信backup/restore/business manifestsource/cutoff/candidate覆盖证据保留期

每个信号写 producer、collector、query、labels、刷新周期、缺失语义、owner、retention、 权限与成本。missing value 不能默认解释成 zero/healthy。

PostgreSQL 证据的时效与局限

PostgreSQL cumulative statistics、pg_stat_activitypg_stat_replicationpg_stat_replication_slotspg_stat_walpg_stat_io 等提供不同观察面,但要记录:

  • counter 是累计值还是当前 gauge;
  • stats reset、server restart 和 failover 是否改变基线;
  • 读取 snapshot、事务和刷新延迟;
  • query text 是否截断或因权限不可见;
  • standby 与 primary 的语义差异;
  • extension/版本是否改变列和统计;
  • NULL、空行与零值分别意味着什么。

日志应使用可解析格式(如 csvlog/jsonlog)和稳定关联字段,但 log_statement=all 可能暴露敏感数据并产生高开销。优先记录必要 identity、duration、SQLSTATE、query ID、 application/client context;query 参数和 payload 按数据分类处理。

指标、日志与告警要能互相落点

一条 page 应先表达 user impact 或 error-budget threat,再链接诊断上下文:

alert
  exact service + SLI window + burn/severity
  -> dashboard
     user outcome + dependency + PostgreSQL/host
  -> runbook
     evidence requests + route predicates + stop line
  -> raw source
     reproducible query/log projection

按每个 instance 发 30 条 alert 通常不如按 service impact 聚合一次,再保留 instance 分解。告警规则也需要单元/合成 time series 测试:正常、阈值边界、缺失数据、抖动和 长期低速 burn 都要覆盖。

时间同步是证据基础设施

至少监控:

clock source and synchronization state
offset / frequency error
last successful sync
host suspend/resume or VM migration
timezone configuration
collector ingestion delay

数据库 now() 是事务开始时间;statement_timestamp()clock_timestamp() 语义不同。应用、PostgreSQL log、systemd journal、proxy 和 monitoring timestamp 还可能分别来自 event time 与 ingest time。复盘合并前先统一 UTC 展示、保留原时区,并标注误差;不能靠肉眼把相近 timestamp 当因果顺序。

缺口行动要可验收

不要写:

增加更多监控。
完善日志。
保证时间准确。

写成:

owner: observability-platform
artifact: pg36_service user-SLI rule revision 3
test: synthetic 5% failure over declared windows
pass: fast window pages; slow burn records ticket; zero/missing remain distinguishable
clock test: inject collector offset fixture and reject order claims below uncertainty
evidence: rule test output + notification trace + dashboard link
revalidate: 30 days

观察能力只有在问题发生前存在、事件中可访问、事件后可重放时,才是一项控制。


上一节:从时间线建立因果链 · 返回本章目录 · 下一节:把行动项变成控制 · 查看全书目录 · 查看索引中心

最后更新于