故障复盘模板:关注系统改进,不追责个人
复盘文档写了,然后呢
我见过不少团队在故障处理完之后,花两三个小时写一份复盘文档。内容很完整,时间线、根因、改进项都有。然后这份文档就被归档到 Wiki 的某个角落,再也没有人打开过。三个月后,类似的故障再次发生。
这不是个别现象。很多团队的复盘停留在「记录故障」这个阶段,没有走到「改进系统」。问题不在态度——大家都想做好——而在方法和结构。一份好的复盘文档,从模板设计开始就要引导写作者把注意力放在系统缺陷上,而不是个人失误上。
这篇文章给出一个可以直接用的复盘模板,同时解释每个字段为什么要这么设计。内容来自 Google SRE 体系、美团工程团队的 5 Whys 实践,以及我自己在多个团队推行复盘文化时踩过的坑。
复盘的理论基础:为什么必须「无责」
Google 在 2014 年出版的《Site Reliability Engineering》一书中用整章篇幅讨论了 Postmortem Culture。核心观点很清晰:人在生产环境中一定会犯错,试图通过追责改变人的行为,不如通过系统设计来容纳错误。
Google 内部的复盘有几条硬规则:
- Blameless(无责):复盘文档不能出现对个人的指责。如果你发现某人在事件中做了不当操作,要问的是「系统为什么允许这个操作发生」,而不是「他为什么这么做」。
- Shared(共享):复盘文档在组织内部广泛公开,不局限于当事团队。其他团队遇到类似系统结构时,能从中受益。
- Actionable(可执行):每个改进项必须有明确的负责人和截止日期。没有行动闭环的复盘只是一篇故障记录。
- Thorough(彻底):根因要追到系统层面。停在三「某人误操作」或「代码写错了」不够,要继续问为什么流程允许误操作、为什么测试没发现、为什么监控没告警。
这套理念的底层逻辑是:每次故障都是系统设计的一面镜子。如果你因为追责而让当事人隐瞒细节,你丢掉的不仅是一次学习机会,还保留了那个会导致下一次故障的系统缺陷。
5 Whys 分析法:从症状到根因
5 Whys 是丰田生产系统发明的根因分析方法,在软件行业被广泛采用。它不是真的只问 5 次——有些问题 3 次就到根因,有些需要 7、8 次甚至更多。Google SRE 内部有时会做「250 Whys」,意思就是不断追问直到触达系统设计层面的根本原因。
方法论的核心是建立「因果链」:每一个 Why 的答案成为下一个 Why 的问题,直到你找到一个可以通过系统改造来解决的原因。
| 追问层次 | 典型方向 | 举例 |
|---|---|---|
| 第 1 层 | 直接触发因素 | 数据库主库宕机 |
| 第 2 层 | 技术原因 | 慢查询耗尽系统资源 |
| 第 3 层 | 流程缺陷 | 慢查询没有在执行前被拦截 |
| 第 4 层 | 工具/平台缺失 | 缺少 SQL 审核和性能卡点 |
| 第 5 层 | 管理机制 | 发布流程没有强制性能回归环节 |
美团工程团队在实践中总结了一条经验:如果追问到「人」就停了,说明分析还没到位。 真正的根因应该是一个系统设计或流程上的缺陷,而非某个人的疏忽。
完整案例:三个真实场景的复盘推演
案例一:数据库主库宕机
场景:某电商平台的 MySQL 主库在下午 3 点突然宕机,订单系统全面不可用,持续 47 分钟。
问题还原:
| 维度 | 内容 |
|---|---|
| 故障时间 | 15:02 - 15:49,共 47 分钟 |
| 影响范围 | 全部下单、支付、库存操作不可用 |
| 用户影响 | 约 12000 笔订单失败,客服工单激增 340% |
| 发现方式 | 用户投诉触发人工排查,监控告警滞后 8 分钟 |
| 恢复方式 | 主从切换,从库提升为新主库 |
5 Whys 追问:
- 为什么主库宕机? ——一条全表扫描 SQL 执行超过 40 分钟,耗尽 CPU 和 IO 资源,导致主库进程 OOM 被系统 Kill。
- 为什么全表扫描 SQL 能上线? ——这条 SQL 在测试环境数据量小(2000 行),执行只要 200ms,性能测试通过。
- 为什么测试环境没有发现? ——测试环境数据量与生产环境差距超过 100 倍,且没有 SQL 审核卡点。
- 为什么没有 SQL 审核卡点? ——半年前评估过引入 SQL 审核工具,但因为「影响发布效率」被搁置。
- 为什么「发布效率」优先级高于「数据安全」? ——缺少故障定级标准和对应的流程卡点决策机制。
根因:不是「有人写了一条慢 SQL」,而是发布流程缺少对数据库变更的性能约束机制,且缺少数据量接近生产的测试环境。
修复方案:
# 反面做法 ❌
# 在复盘文档里写:「要求张三加强 SQL 性能意识」
# 这种改进项无法验证、无法追踪,等于没写
# 正确做法 ✅
# 改进项要落到系统改造上:
action_items:
- id: INC-2026-0412-01
action: 引入 SQL 审核工具,PR 提交后自动执行 EXPLAIN 分析
owner: 基础设施组-李四
due_date: 2026-07-15
priority: P0
type: preventive
- id: INC-2026-0412-02
action: 搭建数据量与生产等比的 Shadow 测试库
owner: DBA 组-王五
due_date: 2026-08-01
priority: P1
type: preventive
- id: INC-2026-0412-03
action: 数据库操作增加慢查询自动熔断(执行超 30s 自动 Kill)
owner: DBA 组-王五
due_date: 2026-07-20
priority: P0
type: mitigative案例二:iOS 客户端大面积闪退
场景:某公司内部 OA 应用的 iOS 端在某次发版后大面积闪退,影响 800+ 员工无法正常打卡和审批。
问题还原:
| 维度 | 内容 |
|---|---|
| 故障时间 | 09:15 - 11:30,共 2 小时 15 分钟 |
| 影响范围 | iOS 端全量用户(800+ 人)启动即闪退 |
| 业务影响 | 当日打卡记录缺失,审批流程阻塞 |
| 发现方式 | 发版后 15 分钟,多个用户反馈 |
| 恢复方式 | 紧急回滚到上一版本 |
5 Whys 追问:
- 为什么闪退? ——服务端接口返回值中一个字段从
string类型改为int,iOS 客户端用旧类型解析时触发异常。 - 为什么接口字段类型变了没人通知客户端? ——后端开发者认为这是「内部优化」,没有走跨团队变更通知流程。
- 为什么没有跨团队变更通知流程? ——有流程文档,但只写了邮件通知,没有人执行。
- 为什么邮件通知没人执行? ——邮件通知是「建议」而非「必须」,且没有自动化卡点。
- 为什么没有自动化卡点? ——API 管理平台没有和发布流程打通,接口变更无法自动触发下游通知。
根因:API 变更管理缺少自动化约束机制,跨团队协作依赖人工邮件通知,且这个「建议」没有执行保障。
修复方案:
# 反面做法 ❌
# 「后端同学下次改接口记得通知客户端」
# 依赖人的记忆和自觉,一定还会再犯
# 正确做法 ✅
# 在工具链层面解决:
action_items:
- id: INC-2026-0318-01
action: API 管理平台增加 Breaking Change 标记,自动通知下游消费方
owner: 平台组-赵六
due_date: 2026-07-30
priority: P0
type: preventive
- id: INC-2026-0318-02
action: iOS 客户端增加接口返回值容错解析(类型不匹配时 fallback 而非 crash)
owner: 移动端组-孙七
due_date: 2026-07-15
priority: P0
type: mitigative
- id: INC-2026-0318-03
action: 建立 API 契约测试,发布前自动验证上下游兼容性
owner: 质量组-周八
due_date: 2026-08-15
priority: P1
type: preventive案例三:全球卫星节点被批量清空
这个案例来自 Google SRE 的实际故障记录,是「无责复盘」的经典教材。
场景:一次常规的服务器机架退役操作,因为一个 API 的输入验证缺陷,导致全球所有卫星节点(边缘代理服务器)的硬盘被清空。
问题还原:
| 维度 | 内容 |
|---|---|
| 故障时间 | 持续约 2 天 |
| 影响范围 | 全球所有边缘代理节点 |
| 用户影响 | 用户请求延迟大幅上升,部分查询丢失 |
| 发现方式 | 全球延迟监控异常 |
| 恢复方式 | 将流量切回核心数据中心,再逐步重装边缘节点 |
事件经过:工程师执行机架退役流程时,第一次运行失败了。他手动重试,但因为流程已经部分执行,系统返回了一个空的机器列表。这个空的列表被送入下游 API,而该 API 的输入验证逻辑有一个缺陷——把空列表解读为「没有筛选条件」,于是把清空操作应用到了所有卫星节点。
5 Whys 追问:
- 为什么全球节点被清空? ——退役操作的 wipe 指令应用到了所有节点,而非目标机架。
- 为什么 wipe 指令应用到了所有节点? ——下游 API 收到空的机器列表,将其解读为「无约束条件」。
- 为什么空列表没有被拦截? ——API 缺少输入验证,没有拒绝空的约束列表。
- 为什么工程师重试了操作? ——第一次执行失败时,没有其他检查机制来阻止盲目重试。
- 为什么单个操作可以影响全部节点? ——系统没有对单次操作的影响范围设置上限。
根因:API 设计缺陷(空列表语义错误)+ 缺少操作范围限制 + 缺少破坏性操作的安全审批机制。
改进方向(Google 的实际处理):
- API 层拒绝接受空约束列表
- 限制单次操作影响的最大节点数
- 破坏性操作增加速率限制
- 高风险操作增加自动化安全检查审批
注意:整个复盘中,没有一处提到「工程师不应该重试」或「工程师应该更小心」。所有改进都指向系统设计。这就是 blameless 文化的实际体现。
复盘流程:从故障发生到闭环改进
这个流程有几个容易忽略的关键点:
1. 复盘初稿要异步写,不要在会议里从零开始
很多人的习惯是拉一个小时的会,大家对着白板从头开始写复盘。这效率很低,而且容易变成讨论会而非分析会。正确做法是指定一个 Owner(通常是故障的 Incident Commander),他在会前先收集好数据、整理好时间线、写好初稿。会议的作用是深化分析和对齐改进项,不是写文档。
2. 改进项必须在会后立即录入任务系统
改进项如果只留在复盘文档里,就会被人遗忘。Google 的经验是:复盘会议结束后,所有改进项要立即录入 Jira、Linear 或你们用的任何任务管理系统,和正常的开发任务一样被跟踪。
3. 设定完成率的底线
incident.io 的实践建议:如果改进项完成率低于 50%,说明复盘只是走形式。健康的团队应该保持在 80% 以上。
| 指标 | 健康值 | 警戒值 | 说明 |
|---|---|---|---|
| 改进项完成率 | ≥ 80% | < 50% | 低于 50% 说明复盘是形式 |
| 故障复发率 | < 5% | > 20% | 同类故障重复出现说明根因没解决 |
| 复盘完成时间 | < 48 小时 | > 1 周 | 拖得越久,细节越模糊 |
| 跨团队阅读量 | 持续增长 | 仅当事团队看 | 复盘的价值在于组织级学习 |
复盘模板:每个字段的设计理由
下面是一份完整的复盘模板结构。我按模块拆解,并说明每个字段为什么存在。
模块一:元信息
# 反面做法 ❌
# 复盘文档没有元信息,三个月后无法检索和关联
title: 数据库故障复盘
# 正确做法 ✅
# 结构化元信息,支持检索、关联和趋势分析
metadata:
incident_id: INC-2026-0412
severity: P1
incident_date: 2026-04-12
authors:
- 李四(基础设施组)
reviewers:
- 王五(DBA 组)
- 赵六(SRE 组)
status: draft # draft → in_review → published → closed
related_incidents:
- INC-2025-1103 # 关联历史类似故障模块二:摘要与影响
# 反面做法 ❌
# 摘要模糊,无法快速评估严重程度
summary: 数据库出了问题,影响了业务,后来修好了。
# 正确做法 ✅
# 量化影响,非本团队的人也能快速理解
summary: |
2026-04-12 15:02 - 15:49,MySQL 主库因慢查询导致 OOM 宕机。
订单系统全面不可用 47 分钟,约 12000 笔订单失败。
根因是发布流程缺少 SQL 性能卡点,全表扫描 SQL 未被拦截。
通过主从切换恢复,已完成 3 项系统改进。
impact:
duration_minutes: 47
affected_users: ~12000
affected_orders: ~12000
slo_budget_consumed: 38%
customer_tickets_increase: 340%模块三:时间线
时间线要用 UTC 时间戳,精确到分钟。每个条目要标注「谁做了什么」和「系统状态变化」。
# 反面做法 ❌
# 时间线粗粒度,丢失关键决策点
timeline:
- 数据库挂了
- 排查了一会儿
- 切换了主从
- 恢复了
# 正确做法 ✅
# 细粒度时间线,包含检测、决策、执行各环节
timeline:
- time: "2026-04-12T15:02:00Z"
event: 慢查询开始执行(事后从 slow query log 回溯)
phase: trigger
- time: "2026-04-12T15:10:00Z"
event: 数据库 CPU 使用率超过 95%,但告警阈值为 98%,未触发
phase: detection_gap
- time: "2026-04-12T15:18:00Z"
event: 客服接到第一个用户投诉「无法下单」
phase: detection
- time: "2026-04-12T15:25:00Z"
event: On-call 工程师确认为数据库问题,发起 P1 事件
phase: triage
- time: "2026-04-12T15:32:00Z"
event: 决定执行主从切换
phase: decision
- time: "2026-04-12T15:41:00Z"
event: 主从切换完成,从库提升为新主库
phase: recovery
- time: "2026-04-12T15:49:00Z"
event: 订单系统恢复,监控确认流量正常
phase: resolved模块四:根因分析
根因分析要区分「直接原因」「促成因素」和「根本原因」。直接原因是触发故障的最后一个环节,促成因素是让故障影响扩大的条件,根本原因是系统设计层面的缺陷。
# 反面做法 ❌
# 根因停留在个人层面
root_cause: 张三写了一条性能很差的 SQL
# 正确做法 ✅
# 分层分析,指向系统设计
root_cause_analysis:
direct_cause: |
一条全表扫描 SQL 执行超过 40 分钟,导致 MySQL 主库 CPU 和 IO 耗尽,
进程被 OOM Killer 终止。
contributing_factors:
- 测试环境数据量(2000 行)与生产环境(2 亿行)差距 100 倍
- 数据库 CPU 告警阈值设为 98%,慢查询在 95% 时已经影响服务但未能触发告警
- 发布流程没有 SQL 审核环节
root_cause: |
发布流程缺少对数据库变更的性能约束机制。
团队在半年前评估过 SQL 审核工具,但因「影响发布效率」搁置,
且缺少故障定级标准来辅助这类优先级决策。模块五:检测缺口
检测缺口是容易被忽略但极其重要的部分。它回答的是:为什么故障发生了,我们没有更早发现?
# 反面做法 ❌
# 不分析检测缺口,只关注「怎么修」
# (没有这个模块)
# 正确做法 ✅
# 明确分析检测和告警的盲区
detection_gaps:
- gap: 数据库 CPU 告警阈值过高(98%),慢查询导致 CPU 95% 时未告警
fix: 将告警阈值调整为 85%,并增加基于趋势的预测告警
owner: SRE 组-钱九
due_date: "2026-07-10"
- gap: 缺少慢查询上线前的自动检测机制
fix: 在 CI/CD 流水线中集成 EXPLAIN 分析
owner: 基础设施组-李四
due_date: "2026-07-15"模块六:改进项
改进项必须遵循 SMART 原则(具体、可衡量、可达成、相关性、有时限),并且分为「预防型」和「缓解型」。
# 反面做法 ❌
# 改进项模糊、无负责人、无截止日期
action_items:
- 加强 SQL 性能优化
- 完善测试环境
- 提高团队意识
# 正确做法 ✅
# 每个改进项都具体、可追踪、有归属
action_items:
- id: INC-2026-0412-01
action: 引入 SQL 审核工具,PR 提交后自动执行 EXPLAIN 分析
owner: 基础设施组-李四
due_date: "2026-07-15"
priority: P0
type: preventive # 防止同类故障再次发生
status: todo
- id: INC-2026-0412-02
action: 数据库 CPU 告警阈值从 98% 调整为 85%
owner: SRE 组-钱九
due_date: "2026-07-10"
priority: P0
type: mitigative # 加快下次类似问题的检测速度
status: todo好/坏做法对比汇总
下面把全文涉及的关键对比集中展示,方便快速参考。
| 维度 | 反面做法 | 正确做法 |
|---|---|---|
| 根因描述 | 「某人误操作」 | 「系统允许误操作发生,缺少防护机制」 |
| 改进项 | 「加强代码审查」 | 「在 CI 中集成自动化检查,阻断不合格代码合入」 |
| 时间线 | 「数据库挂了,后来修好了」 | 按分钟粒度记录,含检测、决策、执行各环节 |
| 影响评估 | 「影响了业务」 | 「12000 笔订单失败,SLO 预算消耗 38%」 |
| 改进项归属 | 「团队负责」 | 具体到某一个人 |
| 改进项截止 | 「尽快」 | 具体日期 |
| 告警规则 | 固定阈值 98% | 结合趋势预测 + 分层阈值 |
| 复盘频率 | 出了事才复盘 | 定期回顾历史复盘的改进项完成情况 |
| 复盘阶段 | 常见问题 | 改进方向 |
|---|---|---|
| 数据收集 | 只收集技术日志,忽略人工决策过程 | 同时记录「谁在什么时候做了什么决策」 |
| 根因分析 | 追到「人」就停了 | 继续追问系统为什么允许这个行为 |
| 改进项制定 | 写「加强培训」「提高意识」 | 写具体的系统改造或流程卡点 |
| 文档撰写 | 开会时从零开始写 | 会前异步完成初稿,会议用于深化分析 |
| 跟踪闭环 | 改进项留在 Wiki 里 | 录入任务管理系统,和开发任务同等对待 |
| 改进项类型 | 定义 | 举例 |
|---|---|---|
| Preventive(预防型) | 防止同类故障再次发生 | 引入 SQL 审核工具,阻断不合规 SQL 上线 |
| Mitigative(缓解型) | 加快下次类似问题的发现和恢复速度 | 调整告警阈值,缩短故障检测时间 |
| Process(流程型) | 改进团队协作和决策流程 | 建立 API 变更的跨团队通知机制 |
| Testing(测试型) | 增加覆盖故障场景的测试 | 增加数据量接近生产的集成测试环境 |
| 复盘成熟度 | 特征 | 典型表现 |
|---|---|---|
| L1 记录级 | 只记录故障经过,不分析根因 | 「数据库挂了,换了台机器好了」 |
| L2 归因级 | 找到直接原因,但停在表面 | 「慢 SQL 导致数据库宕机」 |
| L3 系统级 | 追到系统设计缺陷,提出系统改进 | 「发布流程缺少 SQL 性能卡点」 |
| L4 文化级 | 复盘文档跨团队共享,改进项闭环率 > 80% | 复盘成为组织学习的基础设施 |
复盘执行检查清单
以下清单按复盘流程的时间阶段分组,每次复盘时可以直接对照使用。
阶段一:故障发生后 24 小时内
- 指定唯一的复盘 Owner(通常是 Incident Commander)
- 收集所有相关日志、监控数据、变更记录
- 整理完整时间线,精确到分钟,包含人工决策节点
- 量化影响范围(用户数、订单数、SLO 预算消耗、客服工单量)
- 确认故障严重程度等级(P0/P1/P2/P3)
阶段二:初稿撰写(48 小时内完成)
- 按照模板结构填写所有模块,不留空白
- 根因分析至少追问 5 层,确保触达系统设计层面
- 区分直接原因、促成因素和根本原因
- 明确列出检测缺口:为什么没有更早发现
- 改进项分类为预防型/缓解型/流程型/测试型
- 每个改进项有具体的负责人(一个人,不是「团队」)
- 每个改进项有具体的截止日期(不是「尽快」)
- 改进项优先级排序:P0 项不超过总项数的 30%
阶段三:评审会议
- 会议前至少 24 小时发出初稿,让参与者提前阅读
- 会议聚焦于深化根因分析和对齐改进项,不是从头写文档
- 检查文档语言:消除所有指向个人的指责性表述
- 邀请相关团队参与(上下游依赖方、SRE、安全)
- 会议时长控制在 60 分钟内
阶段四:发布与闭环
- 改进项录入任务管理系统(Jira/Linear),获得任务 ID
- 复盘文档状态标记为 published,通知相关团队
- 每周跟踪改进项完成进度,在周会中同步
- 所有 P0 改进项在 30 天内完成或明确调整计划
- 全部改进项完成后,复盘文档状态标记为 closed
- 跨团队分享:在内部技术博客或周报中摘要关键教训
推动复盘文化的几个实操建议
模板只是工具,文化才是基础。如果你在一个还没有复盘习惯的团队推行这件事,以下是我验证过有效的做法。
从小的开始。不要等 P0 故障才复盘。P3、P4 的小问题更适合练手——影响小,压力低,团队更容易接受。
领导者先做示范。当团队负责人公开承认自己在某个故障中的决策失误,并且把改进指向自己负责的流程时,其他人会跟进。反过来,如果领导者总是问「这是谁的错」,再好的模板也推行不下去。
让复盘文档可见。Google 的做法是让所有复盘文档在公司内部公开可见。你不需要做到这个程度,但至少要让相关团队能方便地检索和阅读。
定期回顾历史复盘。每季度花一个小时,回顾过去三个月的复盘文档,检查改进项完成率,看看有没有同类故障重复出现。这个动作本身就是对复盘文化的强化。
不要追求完美。第一份复盘文档可能只有 60 分,但它比没有复盘强 100 分。先跑起来,再迭代改进。
参考资料
- Google SRE Workbook: Postmortem Culture — Google 官方的复盘文化指南,包含模板结构和推动文化的方法
- GitHub: Postmortem Templates Collection — 汇集 SRE 书籍、Google、Azure、Elastic 等多来源的复盘模板
- 美团技术博客:5 Whys 分析法在美团工程师中的实践 — 美团工程团队的 5 Whys 实战经验分享
- incident.io: SRE Incident Post-mortem Best Practices — 2026 年 SRE 复盘最佳实践,包含改进项跟踪的具体指标
- Atlassian: A Guide to the Incident Postmortem Process — Atlassian 的复盘流程指南和模板
- 快猫星云:SRE 实践真经——可观测性、SLOs、Runbooks 与事故报告 — 从可观测性到结构化事后分析的完整实践
- 阿里云:故障复盘——卓越架构 — 阿里云卓越架构中的故障复盘标准流程
- InfoQ:美图 SRE 故障应急与复盘实践 — 美图 10 年 SRE 经验总结的故障复盘三段式方法