事后分析撰写Skill postmortem-writing

该技能用于在软件开发和运维中撰写无指责的事后报告,进行根因分析、时间线记录和行动项制定,以改进事件响应流程,促进组织学习,防止事件复发。关键词:事后报告、根因分析、无指责文化、DevOps、事件管理、组织学习。

DevOps 1 次安装 2 次浏览 更新于 3/22/2026

name: postmortem-writing description: 撰写有效、无指责的事后报告,包括根因分析、时间线和行动项。用于进行事件回顾、撰写事后文档或改进事件响应流程。

事后分析撰写

撰写有效、无指责的事后报告的全面指南,以推动组织学习并防止事件复发。

何时使用此技能

  • 进行事后事件回顾
  • 撰写事后文档
  • 促进无指责的事后会议
  • 识别根因和贡献因素
  • 创建可操作的跟进项
  • 建立组织学习文化

核心概念

1. 无指责文化

指责导向 无指责
“谁导致了这个问题?” “什么条件允许了这个问题发生?”
“某人犯了错误” “系统允许了这个错误”
惩罚个人 改进系统
隐藏信息 分享学习
害怕发声 心理安全

2. 事后分析触发因素

  • SEV1 或 SEV2 事件
  • 面向客户的停机时间 > 15 分钟
  • 数据丢失或安全事件
  • 可能严重的未遂事件
  • 新的故障模式
  • 需要异常干预的事件

快速开始

事后分析时间线

第 0 天:事件发生
第 1-2 天:起草事后文档
第 3-5 天:事后会议
第 5-7 天:最终化文档,创建工单
第 2 周及以上:行动项完成
季度:回顾跨事件模式

模板

模板 1:标准事后分析

# 事后分析:[事件标题]

**日期**:2024-01-15
**作者**:@alice, @bob
**状态**:草稿 | 审核中 | 终稿
**事件严重性**:SEV2
**事件持续时间**:47 分钟

## 执行摘要

2024 年 1 月 15 日,支付处理服务经历了 47 分钟的停机,影响了大约 12,000 名客户。根因是部署 v2.3.4 中的配置变更触发的数据库连接池耗尽。通过回滚到 v2.3.3 并增加连接池限制解决了事件。

**影响**:

- 12,000 名客户无法完成购买
- 估计收入损失:45,000 美元
- 创建了 847 个支持工单
- 无数据丢失或安全影响

## 时间线(所有时间 UTC)

| 时间  | 事件                                           |
| ----- | ----------------------------------------------- |
| 14:23 | 部署 v2.3.4 完成到生产环境       |
| 14:31 | 首次警报:`payment_error_rate > 5%`          |
| 14:33 | 值班工程师 @alice 确认警报      |
| 14:35 | 开始初步调查,错误率 23% |
| 14:41 | 宣布事件为 SEV2,@bob 加入              |
| 14:45 | 识别数据库连接耗尽       |
| 14:52 | 决定回滚部署                 |
| 14:58 | 开始回滚到 v2.3.3                    |
| 15:10 | 回滚完成,错误率下降          |
| 15:18 | 服务完全恢复,事件解决      |

## 根因分析

### 发生了什么

v2.3.4 部署包括对数据库查询模式的更改,无意中移除了一个频繁调用端点的连接池。每个请求都打开了新的数据库连接,而不是重用池化连接。

### 为什么发生

1. **近因**:`PaymentRepository.java` 中的代码更改将池化 `DataSource` 替换为直接 `DriverManager.getConnection()` 调用。

2. **贡献因素**:
   - 代码审查未捕获连接处理更改
   - 没有针对连接池行为的集成测试
   - 暂存环境流量较低,掩盖了问题
   - 数据库连接指标警报阈值过高(90%)

3. **5 Whys 分析**:
   - 为什么服务失败?→ 数据库连接耗尽
   - 为什么连接耗尽?→ 每个请求打开新连接
   - 为什么每个请求打开新连接?→ 代码绕过连接池
   - 为什么代码绕过连接池?→ 开发者不熟悉代码库模式
   - 为什么开发者不熟悉?→ 没有关于连接管理模式的文档

### 系统图

[客户端] → [负载均衡器] → [支付服务] → [数据库] ↓ 连接池(损坏) ↓ 直接连接(原因)


## 检测

### 什么奏效
- 错误率警报在部署后 8 分钟内触发
- Grafana 仪表板清晰显示连接峰值
- 值班响应迅速(2 分钟确认)

### 什么未奏效
- 数据库连接指标警报阈值过高
- 没有部署相关警报
- Canary 部署本可以更早捕获此问题

### 检测差距
部署在 14:23 完成,但首次警报直到 14:31 才触发(8 分钟)。部署感知警报本可以更快检测到问题。

## 响应

### 什么奏效
- 值班工程师快速识别数据库为问题
- 回滚决策果断
- 事件频道中沟通清晰

### 什么可以改进
- 用了 10 分钟关联问题与最近部署
- 必须手动检查部署历史
- 回滚用了 12 分钟(可以更快)

## 影响

### 客户影响
- 12,000 名唯一客户受影响
- 平均影响持续时间:35 分钟
- 847 个支持工单(受影响用户的 23%)
- 客户满意度得分下降 12 点

### 业务影响
- 估计收入损失:45,000 美元
- 支持成本:约 2,500 美元(代理时间)
- 工程时间:约 8 人小时

### 技术影响
- 数据库主节点经历高负载
- 事件期间某些副本延迟
- 系统无永久损坏

## 经验教训

### 什么做得好
1. 警报在客户报告前检测到问题
2. 团队在压力下有效协作
3. 回滚程序运行顺利
4. 沟通清晰及时

### 什么做得不好
1. 代码审查遗漏关键更改
2. 连接池测试覆盖不足
3. 暂存环境不反映生产流量
4. 警报阈值未正确调整

### 哪里幸运
1. 事件发生在工作时间,团队全在
2. 数据库处理了负载而未完全失败
3. 无其他同时发生的事件

## 行动项

| 优先级 | 行动 | 负责人 | 截止日期 | 工单 |
|----------|--------|-------|----------|--------|
| P0 | 添加连接池行为的集成测试 | @alice | 2024-01-22 | ENG-1234 |
| P0 | 降低数据库连接警报阈值到 70% | @bob | 2024-01-17 | OPS-567 |
| P1 | 文档化连接管理模式 | @alice | 2024-01-29 | DOC-89 |
| P1 | 实现部署相关警报 | @bob | 2024-02-05 | OPS-568 |
| P2 | 评估 canary 部署策略 | @charlie | 2024-02-15 | ENG-1235 |
| P2 | 用类似生产流量负载测试暂存环境 | @dave | 2024-02-28 | QA-123 |

## 附录

### 支持数据

#### 错误率图
[链接到 Grafana 仪表板快照]

#### 数据库连接图
[链接到指标]

### 相关事件
- 2023-11-02:用户服务中类似连接问题(POSTMORTEM-42)

### 参考
- [连接池最佳实践](internal-wiki/connection-pools)
- [部署运行手册](internal-wiki/deployment-runbook)

模板 2:5 Whys 分析

# 5 Whys 分析:[事件]

## 问题陈述

支付服务因数据库连接耗尽经历 47 分钟停机。

## 分析

### Why #1: 为什么服务失败?

**答案**:数据库连接耗尽,导致所有新请求失败。

**证据**:指标显示连接数在 100/100(最大),有 500+ 待处理请求。

---

### Why #2: 为什么数据库连接耗尽?

**答案**:每个传入请求打开了新的数据库连接,而不是使用连接池。

**证据**:代码差异显示直接 `DriverManager.getConnection()` 而不是池化 `DataSource`。

---

### Why #3: 为什么代码绕过连接池?

**答案**:开发者重构存储库类,无意中更改了连接获取方法。

**证据**:PR #1234 显示更改,是在修复另一个错误时做出的。

---

### Why #4: 为什么在代码审查中未捕获?

**答案**:审查者专注于功能更改(错误修复),未注意到基础设施更改。

**证据**:审查评论仅讨论业务逻辑。

---

### Why #5: 为什么没有针对此类更改的安全网?

**答案**:我们缺乏验证连接池行为的自动化测试,并且缺乏关于我们连接模式的文档。

**证据**:测试套件没有连接处理测试;维基没有关于数据库连接的文章。

## 识别出的根因

1. **主要**:缺少基础设施行为的自动化测试
2. **次要**:架构模式文档不足
3. **第三**:代码审查清单不包括基础设施考虑

## 系统性改进

| 根因    | 改进                       | 类型       |
| ------------- | --------------------------------- | ---------- |
| 缺少测试 | 添加基础设施行为测试 | 预防 |
| 缺少文档  | 文档化连接模式      | 预防 |
| 审查差距   | 更新审查清单           | 检测  |
| 无 canary     | 实现 canary 部署      | 缓解 |

模板 3:快速事后分析(轻微事件)

# 快速事后分析:[简短标题]

**日期**:2024-01-15 | **持续时间**:12 分钟 | **严重性**:SEV3

## 发生了什么

API 延迟因缓存刷新后的缓存未命中风暴飙升至 5 秒。

## 时间线

- 10:00 - 为配置更新启动缓存刷新
- 10:02 - 延迟警报触发
- 10:05 - 识别为缓存未命中风暴
- 10:08 - 启用缓存预热
- 10:12 - 延迟正常化

## 根因

轻微配置更新的完整缓存刷新导致雷群效应。

## 修复

- 立即:启用缓存预热
- 长期:实现部分缓存失效(ENG-999)

## 经验

不要在生产中完全刷新缓存;使用定向失效。

促进指南

运行事后会议

## 会议结构(60 分钟)

### 1. 开场(5 分钟)

- 提醒每个人无指责文化
- “我们在这里学习,而不是指责”
- 回顾会议规范

### 2. 时间线回顾(15 分钟)

- 按时间顺序走过事件
- 询问澄清问题
- 识别时间线差距

### 3. 分析讨论(20 分钟)

- 什么失败了?
- 为什么失败?
- 什么条件允许了此情况?
- 什么本可以预防?

### 4. 行动项(15 分钟)

- 头脑风暴改进
- 按影响和努力优先级排序
- 分配负责人和截止日期

### 5. 结束(5 分钟)

- 总结关键学习
- 确认行动项负责人
- 如果需要,安排跟进

## 促进技巧

- 保持讨论在轨道上
- 将指责转向系统
- 鼓励安静参与者
- 文档化不同意见
- 时间限制切线

要避免的反模式

反模式 问题 更好方法
指责游戏 关闭学习 专注于系统
浅层分析 不防止复发 问“为什么” 5 次
无行动项 浪费时间 总有具体下一步
不切实际的行动 从未完成 范围到可完成的任务
无跟进 行动被遗忘 在工单系统中跟踪

最佳实践

  • 立即开始 - 记忆快速消退
  • 具体 - 精确时间、精确错误
  • 包括图表 - 视觉证据
  • 分配负责人 - 无孤儿行动项
  • 广泛分享 - 组织学习

不做

  • 不要指名道姓 - 永远
  • 不要跳过小事件 - 它们揭示模式
  • 不要变成指责文档 - 那会扼杀学习
  • 不要创造忙碌工作 - 行动应有意义
  • 不要跳过跟进 - 验证行动完成

资源