目录
3823 字
19 分钟
线上事故复盘会上的经典台词

周三 14:00,复盘会。

会议室里坐着九个人,投屏上是一条已经恢复的曲线。主持人开场:「今天不追责,就事论事,主要把过程捋一遍。」

14:06,有人说:「其实这个风险我们早就知道。」

14:07,另一个人接:「但当时谁也没想到会这么严重。」

会议正式进入经典台词环节。

一、复盘会台词博物馆#

「先说说当时是谁操作的?」#

这句话通常出现在会议的前五分钟,语气平和,甚至带着一点「我只是想还原现场」的真诚。

它的问题不在于问操作者,而在于问完操作者就结束了。操作者是最后一个碰到系统的人,不是事故发生的原因。真正该问的是:他当时看到了什么?界面让他觉得哪个选项更安全?为什么在 02:13 那个时刻,那个操作看起来是合理的?

事故复盘里有一个很有用的区分:第一故事和第二故事。第一故事是「谁在什么时候做了什么」;第二故事是「在他的信息、压力和时间约束下,为什么这件事看起来是对的」。只讲第一故事,你得到的是一份行为记录;讲到第二故事,你才拿得到能改系统的东西。

「这是个极小概率事件」#

「小概率」是复盘会上最有效的一句止痛药。说完之后,会议室的空气都会松一点。

但概率离开暴露面就没有意义。一个接口单次请求出错的概率是 0.1%,听起来很小;如果每天有一万次请求,期望值就是每天十次。如果这个接口只在每年一次的对账任务里被调用,那它确实可以往后放。

所以「小概率」不是一个结论,而是一道没算完的题:单次概率是多少?每天触发多少次?最坏后果是什么? 三个数不放在一起,概率就只是情绪管理工具。

「为什么没有告警?」#

这句话本身没错,错在它经常被当成句号,而不是问号。

告警能缩短发现时间,但不能阻止事故发生。更麻烦的是,复盘会上一说「没有告警」,行动项很容易变成「加个告警」——然后系统里多了一条每天都响、所有人都学会忽略的规则。

更有价值的是接着问:这个盲区存在多久了?在告警之外,当时还有哪些信号其实已经出现?我们是靠用户投诉知道的,还是靠监控知道的?如果下次是同样的盲区,我们能不能更早地看见它?

「我们早就知道这里有问题」#

这是全场最诚实、也最容易被浪费的一句话。

如果大家早就知道,那这次事故就不是「意外」,而是一次已知风险被接受了。真正值得追问的是:它为什么一直没被排进迭代?是被更大的需求挤掉了,还是评估下来觉得可以接受?当时做这个取舍的人,掌握了哪些信息?

「早就知道」不应该让会议陷入尴尬,它应该把讨论从「谁犯了错」拉到「组织如何对待已知风险」。这两件事的修复方式完全不同。

「这个我们线下再对齐」#

「线下对齐」是行动项的墓地。

它听起来很务实:会上时间有限,细节会后聊。问题是,一旦离开这个唯一有记录、有旁听者、有截止时间的场合,这件事就只剩下两个人的模糊记忆。两周后有人问「上次说的那个改动做了吗」,答案是「还在对齐」。

如果一件事值得在复盘会上提出来,它就值得当场留下三样东西:谁负责、什么时候给结论、结论写在哪。 做不到这三样,不如直接写进「本次不处理」并说明原因——至少它是诚实的。

「下次注意」「加强意识」#

这两句话的共同点是:不可验证、不可分配、不可关闭。

「注意」是一个人的心理状态,不是一个系统变更。它无法写进排期,无法验收,也无法在下一次复盘时回答「我们做到了吗」。更现实的问题是:如果这次事故需要靠「更注意」来避免,那说明系统把太多正确性押在了人的临场状态上——而人总会困、会急、会同时处理三件事。

把「加强意识」翻译成工程语言,通常会长成:加一个默认安全的选项、把危险操作变成两步确认、把检查放进 CI、把权限收窄。能落到系统里的,才叫行动项。

「我已经在 PR 里加了个检查」#

这是所有台词里最像「已经修好了」的一句。

加检查本身没错,但要问两个问题:它能防住这次事故吗?它能防住下一次变体吗?如果这次是一个字段被写成字符串,而新加的检查只匹配那个具体字段名,那它防住的是历史,不是未来。

好的防护动作通常指向一类错误,而不是一次错误:不是「禁止这个值」,而是「这个接口只接受枚举,其他一律拒绝」。前者是补丁,后者是约束。

「这次复盘挺成功的」#

一场会按时结束、大家没有吵起来、文档也写了,确实不容易。

但复盘的成功标准不是会议体验,而是它有没有改变一个决定。如果文档归档之后,排期没变、设计没变、值班流程没变、下一个人面对同样的界面仍然会做出同样的选择,那这场会只是把事故重新描述了一遍。

二、这些台词为什么会出现#

把上面这些话全归因于「大家爱甩锅」,有点偷懒。它们之所以反复出现,是因为复盘会同时背了三个互相打架的任务:

  1. 学习:搞清楚系统为什么会这样;
  2. 问责:给组织一个交代;
  3. 交差:证明我们已经处理过了。

学习需要完整的信息,问责会让人隐藏信息,交差则倾向于尽快结束。三件事挤在一个小时里,最省力的策略就是把问题收缩到一个人、一个操作、一个「下次注意」。

还有一个更隐蔽的机制:后见之明。事故发生之后,我们知道结局,于是当时那个选择看起来愚蠢得显而易见。「他怎么会没想到?」——但他当时没有结局,只有半截日志、一条模糊的告警和旁边催着恢复业务的群消息。

Sidney Dekker 在讨论人为失误时区分了两种视角:旧视角认为「人的错误导致系统失败」,新视角认为「人的错误是系统问题的症状」。旧视角的终点是找到那个「坏苹果」;新视角的起点是搞清楚,为什么在这个系统里,一个正常的人会做出这个动作。

Richard Cook 在《How Complex Systems Fail》里说得更直接:复杂系统的事故通常是多个小失效叠加的结果,事后把某一点命名为「根因」,在根本上是一种简化。配置变更、重试放大、监控盲区、交接班的信息丢失——拿掉其中任何一个,事故都可能不发生,但这不等于其中任何一个是「唯一原因」。

Diane Vaughan 研究挑战者号事故时提出过「偏差的常态化」:一个偏离规范的做法,因为一直没有出事,就慢慢被当成正常流程的一部分。放到软件系统里,就是那句「我们一直这么干的,也没出过问题」。它和「我们早就知道有风险」是同一枚硬币的两面。

所以,台词不是谎言。它们大多是人在一个高压、模糊、又要给交代的场合里,本能地选择的低成本解释。问题是,低成本解释会带来高成本的未来。

三、把台词翻译成问题#

台词它实际在说什么可以接着问
「这不是我的锅」我在保护自己这个决定在当时有哪些合理约束?哪个环节本可以更早拦住它?
「极小概率」我还没算暴露面单次概率多少?每天触发多少次?最坏后果是什么?
「没有告警」我们靠人肉发现了它盲区存在多久?还有哪些信号被忽略了?
「早就知道」这是一个被接受的风险它为什么一直没排上优先级?谁做的取舍?
「线下对齐」这件事不会再有记录谁负责?什么时候给结论?写在哪里?
「下次注意」我们没找到系统改法能不能变成默认安全、检查或权限约束?
「加了个检查」我们防住了这一次它能防住下一次变体吗?

四、一场能留下东西的复盘,长什么样#

1. 先时间线,后解释#

时间线至少要有五个点:

  • 用户第一次受到影响;
  • 系统第一次发出信号;
  • 人第一次注意到;
  • 第一次缓解动作生效;
  • 完全恢复。

这五个点把「事故多长」拆成了「发现多慢」和「恢复多慢」。很多争论会在填时间线的过程中自己消失——因为大家发现彼此说的根本不是同一个时间段。

写时间线时只写事实和决策点,不写评价。「02:13,值班同学执行了回滚」是事实;「02:13,值班同学慌乱中错误回滚」是解释。解释可以晚一点再给。

2. 用「贡献因素」代替「根因」#

与其问「根因是什么」,不如把因素分成几类:

  • 触发因素:直接点火的那次变更、那个请求;
  • 潜在条件:长期存在的配置、耦合、文档缺失;
  • 检测缺口:为什么没更早发现;
  • 响应缺口:为什么恢复花了这么久;
  • 恢复缺口:为什么回滚/切换没有按预期生效。

一张贡献因素图通常比一条「五个为什么」的链子更接近现实。五个为什么的毛病是:它默认只有一条因果链,而且很容易在第一个听起来合理的答案处停下——「因为操作失误」——然后再也不往下问。

3. 用数据校正直觉#

Dan Luu 在总结自己读过的复盘时提到两个反复出现的模式:错误处理代码出问题的比例被严重低估;配置变更则是大型事故的常客。他引用的一项研究分析了几百个分布式系统 bug,其中 48 个严重故障里有 92% 与错误处理不当有关;而在公开的「global outage postmortem」里,大约一半与配置变更有关(这个样本并不代表全部事故,但足够说明配置不是小角色)。

这对复盘会有个直接提醒:别只盯着新写的那几行业务代码。 错误处理路径、配置变更、默认值、回滚脚本,往往才是事故喜欢待的地方。

4. 行动项要能被验收#

一个合格的行动项至少要有:

  • 唯一 owner(不是「团队」,不是「相关同学」);
  • 截止日期;
  • 验证方式(测试、演练、指标、审计都行);
  • 类型:预防、检测、缓解、恢复,四类至少知道自己属于哪类;
  • 一句「它能防住这次吗?能防住下一次变体吗?」的答案。

如果做不完,还要有明确的延期或取消决定。行动项最怕的不是延期,是没人记得它曾经存在。

五、无责,不等于无人负责#

「无责复盘」经常被误解成「出了事也没人需要负责」。这两件事不是一回事。

更准确的框架来自「公正文化」(just culture):对无心的失误,以安慰和改进为主;对明知有风险仍图省事的行为,要辅导和纠正;对明知故犯、隐瞒或鲁莽的行为,才需要纪律处理。无责保护的是「说实话的人」,不是「所有行为」。

换句话说,复盘不审判一个人在深夜做出的判断,但要追问组织为什么让这个判断成为最容易的选择;同时,行动项的负责人仍然要为自己的承诺负责。对事不对人,不等于对交付也不对事。

六、主持人可以带上的七个问题#

  1. 用户第一次受影响是什么时候?我们什么时候知道的?
  2. 当时值班的人看到了什么?他为什么觉得那个操作是对的?
  3. 哪些防护本该拦住它?为什么没有拦住?
  4. 如果同样的条件再来一次,哪一步最可能不同?
  5. 这次我们运气好在哪?(有没有 near miss 被忽略了?)
  6. 每个行动项由谁负责,什么时候验证?
  7. 这次复盘改变了哪一条设计、流程或默认值?

第七个问题是整场会的验收标准。答不上来,文档写得再漂亮,也只是事故的墓碑。

写在最后#

复盘会最有意思的地方在于:它表面上在讨论过去,实际上在训练组织未来如何解释失败。

如果每次事故最后都归结为「某人不够小心」,那组织学到的唯一教训就是「下次换个人」。如果每次都能往下挖一层——界面为什么容易点错、默认值为什么危险、告警为什么没人看、已知风险为什么排不上——那事故才会真正变成系统的一部分记忆。

所以,下次再听到「这不是我的锅」,可以试着接一句:

同意,先不找锅。我们来看看,当时为什么看起来像一口锅。

事故总会发生。好的复盘不承诺它不再发生,只承诺同一类事故不再以同样的方式发生。

参考来源#

延伸阅读:本博客里还有几篇和「事故与解释」有关的文章——《技术黑话词典》逐条翻译的是开发过程中的甩锅用语,这篇关注的是复盘会本身和它的产出;《周五上线魔咒》讲的是部署时机的选择;《可观测性三支柱》讲的是怎么更早看见问题;《历史上的著名 Bug》则是几场事故的现场记录。

线上事故复盘会上的经典台词
https://www.hehonglei.cn/posts/incident-postmortem-classic-lines/
作者
Honglei He
发布于
2026-10-18
许可协议
CC BY-NC-SA 4.0