一次线上故障的完整复盘

九月二十八号下午两点零六分,站点开始返回 502。十七分钟后恢复。这篇是完整的复盘记录,包括我们做错的地方。

时间线

时间 事件
14:06 监控告警,网关 502 比例超过阈值
14:09 值班同学介入,初步判断为后端服务不可用
14:12 发现数据库连接池打满
14:18 定位到某个慢查询,临时限流
14:23 服务恢复,错误率回落

根因

一个三年前写的定时任务,每天下午两点扫全表。三年前表里只有两万行,现在有两千万行。

1
SELECT * FROM user_events WHERE created_at > ? ORDER BY created_at;

created_at 上没有索引。这个查询在小数据量时没问题,数据量涨了一千倍之后,单次执行从 200ms 变成 90 秒,直接占满连接池。

我们做错的三件事

  1. 监控只覆盖了结果,没覆盖趋势。 慢查询的执行时长是缓慢恶化的,如果有趋势告警,三个月前就该发现了。
  2. 没有对定时任务做资源隔离。 它和在线请求共用连接池,一个离线任务拖垮了在线服务。
  3. 恢复依赖人工判断。 从告警到限流花了十二分钟,其中七分钟花在”确认是不是这个问题”上。

改进行动

  • 给所有定时任务单独的连接池,上限为在线池的 20%
  • 补齐慢查询趋势告警,超过历史均值三倍即触发
  • 为这类”已知可疑查询”准备一键限流脚本,把恢复时间压到两分钟内

故障本身不复杂,复杂的是它安静地恶化了三年却没人发现。这才是真正要修的东西。


一次线上故障的完整复盘
http://example.com/posts/incident-review/
作者
博主
发布于
2026年9月30日
许可协议