事故复盘方法论
Blameless Postmortem、5-Whys根因分析与复盘报告。
1. 从”飞机失事调查”说起
1.1 航空业教给软件业的一课
航空业有一个著名的原则:每一次空难都会被极其严肃地调查,而调查的目的不是”惩罚飞行员”,而是”让这类事故永不重演”。
调查员会做三件事:
- 找到黑匣子——记录飞行全程数据的设备,重建”发生了什么”
- 还原时间线——每一分钟、每一个操作、每一个系统状态
- 找出系统原因——是飞机设计缺陷?培训不足?流程漏洞?还是多个因素叠加?
航空业把每一次事故都变成一次”系统改进的机会”:新的检查单、新的设计标准、新的培训内容。今天你坐飞机之所以安全,正是因为几十年来一代又一代的事故调查,把各种可能的失败模式都变成了预防措施。
软件行业的事故复盘(Postmortem)学的是同一件事:系统出故障后,不是”揪出责任人”,而是通过系统化的调查,找到让故障发生的”系统缺陷”,并把它修复,让同类事故不再重演。
1.2 什么是 Postmortem
Postmortem(事后总结/事故复盘)的定义:
Postmortem 是一份书面记录,描述一次事故”发生了什么、造成了什么影响、我们如何响应、根本原因是什么、以及为了防止重演我们要采取什么行动”。
它不是一个”批斗会”,而是一份学习文件。Google SRE 书中的核心观点值得反复读:
“书写事后总结不是一种惩罚,而是整个公司的一次学习机会。”
1.3 复盘的价值
- 防止重演:找出根因并修复,让”同一类事故”不再发生(事故不可避免,但重复的事故可以避免)
- 沉淀经验:把这次踩的坑写下来,下次遇到类似问题,直接有路可走
- 暴露系统弱点:很多事故是”多重小缺陷叠加”的结果——复盘能发现这些平时看不见的弱点
- 建立信任:透明地复盘,让团队敢于承认问题,而不是隐瞒问题(隐瞒才是最大的隐患)
2. 无指责文化(Blameless Culture):复盘的第一块基石
2.1 复盘最大的敌人:恐惧
假设你犯了一个错误导致线上事故。公司有两种处理方式:
方式 A:追责。你被批评、被扣绩效、写检讨。→ 你的反应是:下次出错藏起来,自己偷偷修,不让别人知道。
方式 B:无指责复盘。大家坐下来分析”是系统里哪个环节让这个错误成为可能”。→ 你的反应是:坦承发生了什么,和大家一起找系统缺陷。
方式 A 的致命后果:错误被隐藏,系统缺陷没有被修复。同样的错误会在别人身上再犯,而且因为没人讨论,永远发现不了。指责不是解决安全问题的方式,隐瞒才是。 航空业早就明白:如果飞行员因为害怕被处罚而隐瞒操作失误,航空安全数据就是假的,灾难性事故只会更多。
2.2 无指责复盘的假定
无指责复盘建立在一个关键假定上(源自 John Allspaw 的经典文章”Blameless PostMortems and a Just Culture”,2012):
参与事故的每个人都是出于善意,并且基于当时掌握的信息,做出了在当时看来最合理的决定。
基于这个假定,复盘问的问题从”谁做错了什么?“变成”什么系统因素让错误变得容易发生?”:
- 不是”小张忘了检查磁盘空间”,而是”为什么系统没有在磁盘快满时自动告警?”
- 不是”小李用错了命令”,而是”为什么删除命令没有二次确认?”
- 不是”老王没看文档”,而是”为什么文档存在但没人知道它在那里?”
2.3 无指责 ≠ 零问责
这里有一个常见误解:无指责 = 谁都不用负责 = 犯错了也没事。
真相是:无指责复盘和问责制并不矛盾。复盘依然会产生行动项(Action Items),每一项都有负责人、有截止日期、必须落实。它问责的对象是”系统改进”,而不是”个人错误”。
区别在于:
| 维度 | 指责文化 | 无指责文化 |
|---|---|---|
| 关注点 | 谁犯的错 | 系统哪里允许这个错发生 |
| 结果 | 处罚个人 | 修复系统 |
| 信息 | 被隐瞒 | 被坦诚分享 |
| 团队感受 | 恐惧、防御 | 心理安全、学习 |
3. 根因分析:5-Whys 方法
3.1 什么是 5-Whys
5-Whys(五次为什么)起源于丰田生产系统,是根因分析最经典的工具。方法简单到极致:
对问题连续追问”为什么”,每次追问都用上一个答案作为新问题的基础,通常问 5 次就能从”表面现象”追到”系统根因”。
3.2 一个完整的 5-Whys 案例
问题:网站响应超时。
第 1 问:为什么网站响应超时?
答:数据库查询很慢。
第 2 问:为什么数据库查询很慢?
答:一个关键查询缺少索引,走了全表扫描。
第 3 问:为什么新增的查询没有加索引?
答:代码审查时没有人检查这条查询的索引情况。
第 4 问:为什么代码审查没检查索引?
答:审查清单里没有"数据库查询性能"这个检查项。
第 5 问:为什么审查清单会漏掉这个检查项?
答:清单是两年前写的,当时团队还没有数据库性能问题,
之后从未系统性地更新过审查清单。
看这条链的终点:真正的根因不是”数据库查询慢”(那是症状),也不是”没加索引”(那是直接原因),而是**“审查清单两年未更新,缺少数据库性能检查项”**——这是一个可以修复的系统缺陷。
修复行动:更新代码审查清单,增加数据库查询性能检查项;同时为数据库增加慢查询自动告警(这样即使以后再有漏网之鱼,也能在监控层面兜底)。
3.3 5-Whys 的注意事项
-
不要停在”人”身上。 “因为小张忘了”不是根因,是借口。继续问:“为什么小张会忘?流程上如何防止?”
-
至少追问 3 层。 停在第一层(“数据库慢”)往往得不到可执行的修复——除非你能回答”为什么数据库会慢”。
-
不要过度深挖。 5 层通常够用。继续追问到”宇宙起源”没有意义,找到”可以采取行动的那一层”就停。
-
允许分支。 一次事故往往有多个原因链(技术链 + 检测延迟链 + 响应延迟链),每条链都要追。
-
重视”检测与响应”链。 很多事故不是”没坏”,而是”坏了很久没人发现”。如果事故是因为”没被及时发现”而升级的,要单独追问:“为什么没能更早发现?”
4. 复盘报告:结构化模板
复盘报告是复盘的产出物。一份好报告应该让”没参与事故的人”也能完全理解发生了什么。以下是经过实践检验的模板:
# 事故复盘:订单服务 503 故障(2026-08-02)
## 基本信息
- 事故时间:2026-08-02 02:15 - 02:47(共 32 分钟)
- 影响范围:订单查询接口全线 503,下单功能受影响
- 受影响用户:约 12 万活跃用户
- 严重级别:Sev1
- 值班工程师:小周
- 复盘时间:2026-08-03(事故后 24 小时)
## 摘要(Executive Summary)
2026-08-02 凌晨 2:15,订单服务因数据库连接池被打满而整体不可用,
持续 32 分钟。直接原因是凌晨 2:00 上线的批量任务与线上流量同时
争抢数据库连接。根本原因是连接池上限设置过小且缺少连接池使用率
告警。已修复连接池配置、增加告警、并更新部署检查清单。
## 时间线(Timeline)
| 时间 | 事件 |
| :--- | :--- |
| 02:00 | 批量对账任务部署上线 |
| 02:15 | 告警触发:订单服务错误率 > 5% |
| 02:17 | 值班工程师确认告警,开始排查 |
| 02:22 | 确认数据库连接池耗尽(active=200/200) |
| 02:25 | 暂停批量任务,连接逐步释放 |
| 02:31 | 错误率回落至 < 1% |
| 02:47 | 确认服务完全恢复,关闭事故 |
| 03:00 | 启动复盘流程,通知相关方 |
## 影响评估(Impact)
- 用户可见影响:订单查询失败、下单超时
- 数据影响:无数据丢失(写入未受影响)
- 业务影响:32 分钟不可用,约等于月度错误预算的 0.7%
- 外部沟通:状态页 02:25 发布,02:50 标记已恢复
## 根因分析(Root Cause)
### 直接原因
数据库连接池(max 200)被凌晨 2:00 启动的批量对账任务耗尽,
线上流量请求无法获取连接,全部等待超时。
### 根本原因(5-Whys 链)
1. 为什么订单服务 503?→ 连接池耗尽,请求拿不到连接
2. 为什么连接池耗尽?→ 批量任务瞬时占用 180+ 连接
3. 为什么批量任务与线上流量争抢连接?→ 部署时未评估
批量任务对连接池的占用
4. 为什么未评估?→ 部署检查清单没有"资源占用评估"环节
5. 为什么检查清单缺失?→ 清单未随系统演进更新,且连接池
使用率无告警,问题在"无人察觉"中逐步放大
### 其他贡献因素
- 连接池使用率没有监控(如果 02:00 就告警,可在影响用户前干预)
- 批量任务未设置"错峰"执行(可配置为凌晨低峰)
## 改进行动(Action Items)
| # | 行动 | 负责人 | 截止日期 | 优先级 |
| :--- | :--- | :--- | :--- | :--- |
| 1 | 连接池上限 200 → 500,并设置等待队列超时 | 小周 | 08-03 | P0 |
| 2 | 增加"连接池使用率"监控与告警(>80% 告警) | 小李 | 08-03 | P0 |
| 3 | 部署检查清单增加"资源占用评估"环节 | 小周 | 08-05 | P1 |
| 4 | 批量任务改为可配置错峰执行 | 小王 | 08-07 | P1 |
| 5 | 本复盘纳入团队季度 Review | 技术负责人 | 09-30 | P2 |
## 经验教训(Lessons Learned)
### 做得好的
- 告警在 2 分钟内触发,响应迅速
- 止血决策正确:先暂停批量任务释放连接
### 需要改进的
- 连接池这类"容量类"指标没有纳入监控
- 批量任务上线前缺少资源评估
### 幸运的地方
- 事故发生在凌晨低峰,影响面相对可控
- 没有造成数据丢失
## 附录
- 相关告警截图、日志链接、代码变更记录
4.1 模板中的五个关键部分
- 摘要:给忙碌的读者(包括管理层)看的 2-3 句话总结
- 时间线:复盘的”黑匣子”,按分钟记录,是所有分析的依据
- 根因分析:直接原因 + 根本原因(5-Whys),区分”症状”和”病因”
- 改进行动:复盘的”产出”,每项都有负责人、截止日期、优先级——没有行动项的复盘是空谈
- 经验教训:做得好的 / 需要改进的 / 幸运的地方(“幸运”这一栏非常重要——它提醒团队哪些环节只是”运气好”才没出事)
5. 复盘会议:怎么开一场有效的复盘
复盘会议的目标是集体学习,不是”读报告”。流程参考:
1. 主持人开场:说明目的(学习,不是追责) (5 min)
2. 值班工程师讲述时间线 (10 min)
3. 集体讨论根因:5-Whys 逐层过,允许补充 (15 min)
4. 制定改进行动:明确负责人与期限 (10 min)
5. 总结:确认"幸运的地方"与"下次要避免的" (5 min)
5.1 主持人的职责
- 保护心理安全:一旦有人开始指责他人,主持人要及时把话题拉回”系统因素”
- 控制节奏:每个环节限时,避免在某个细节上无休止争论
- 确保参与:让沉默的人发言,他们可能有不同的视角
- 落实产出:确认每个行动项都有主人和期限
5.2 何时触发复盘
不是每次事故都要完整复盘。触发条件通常是:
- 用户可见的宕机或服务降级
- 任何数据丢失
- 值班工程师被人工介入(说明自动化没兜住)
- 事故持续时间过长(超过既定阈值)
- 监控没发现、靠人工发现的问题(说明监控有盲区)
时间要求:事故后 48 小时内完成复盘。拖得越久,细节遗忘得越多,复盘质量越差。
6. 复盘文化:让”学习”成为团队习惯
6.1 复盘文化的五个要素
| 要素 | 说明 |
|---|---|
| 及时性 | 事故后 48 小时内完成 |
| 全员参与 | 相关人员都要参加,包括新人和旁观者 |
| 文档公开 | 复盘报告全员可查(经验共享) |
| 跟踪闭环 | 改进行动必须落实,季度回顾执行情况 |
| 定期回顾 | 定期审视”复盘改进行动是否真正减少了事故” |
6.2 让复盘文化落地的小技巧
- 复盘阅读俱乐部:每月挑一份”最有价值”的复盘报告,团队一起精读
- 季度复盘回顾:回顾本季度的改进行动,哪些完成了、哪些没有、没有的原因是什么
- “本月最佳复盘”:表彰写得最坦诚、最有学习价值的复盘,传递”坦诚是被鼓励的”信号
- 预演(Premortem):在做大事之前(上线大版本、大重构),先假设”它失败了,为什么会失败”,提前想好失败模式——这是复盘的”前向版本”
6.3 复盘的常见失败模式
失败一:复盘变成批斗会。 主持人一开口就是”这次事故谁的责任”,全场防御。→ 结果:没人说真话,报告全是”官方话术”。
失败二:行动项无人跟踪。 复盘会开完,行动项列了一堆,一个月后没人落实。→ 结果:同样的错误换个场景再犯一遍。
失败三:报告写给自己看。 报告冗长、术语堆砌、只有当事人才看得懂。→ 结果:其他人无法从中学到东西。
失败四:只追技术原因,不追流程原因。 “数据库配置错了”是技术原因,但”为什么配置错了没被发现”是流程原因——后者往往才是真正需要修复的。
7. 常见误区
误区一:复盘 = 找责任人
错误认知:复盘就是查清楚”谁干的”,然后处理谁。
真相:复盘的目的恰恰相反——把注意力从”人”转移到”系统”。系统缺陷修复了,换谁做这个操作都不会出错;只惩罚个人,下次换个人还会踩同一个坑。
误区二:事故一定是”某个人的错误”
错误认知:出事故一定有人做错了什么。
真相:大多数事故是系统性原因的叠加:流程缺失、工具缺陷、信息不透明、监控盲区……单个人只是”压垮骆驼的最后一根稻草”。复盘要找出的是”骆驼的背”为什么这么脆弱。
误区三:复盘报告写完就完事
错误认知:报告归档,任务结束。
真相:报告只是开始。真正的产出是行动项及其落实。 没有落实的行动项 = 没有复盘。
误区四:只有大事故才值得复盘
错误认知:小问题不用复盘,浪费时间。
真相:小问题反复发生,往往是更大问题的前兆。“连接池偶发打满”不追根因,几个月后可能就是”高峰期大面积 503”。小事故用轻量复盘(10 分钟 + 简短报告),大事故用完整复盘。