一次线上接口超时,排查了六个小时,最后发现是一个很小的问题。记录下来,希望别人不要再踩。
现象
每天上午 10 点左右,某个查询接口 P99 从 80ms 涨到 3s 以上,持续约 10 分钟后自行恢复。
排查过程
1. 先看监控
CPU、内存、连接数都没明显变化,只有慢查询数量飙升。
2. 抓慢查询
SELECT * FROM orders
WHERE created_at > $1
ORDER BY created_at DESC
LIMIT 20;执行计划显示走了全表扫描。created_at 上明明有索引。
3. 真相
传入的参数是字符串,而字段是 timestamptz,类型不匹配导致索引失效。上午 10 点恰好有一个定时任务用字符串传参。
修复
- 参数改成强类型绑定
- 增加了一条索引
- 补充了一个回归用例
$stmt = $pdo->prepare('SELECT * FROM orders WHERE created_at > ? ORDER BY created_at DESC LIMIT 20');
$stmt->execute([new DateTimeImmutable($input)]);复盘
- ✓参数类型必须在入口处校验
- ✓慢查询告警阈值从 1s 调到 500ms
- 给所有时间字段查询补一遍索引检查
教训:索引存在不等于索引生效,类型隐式转换是最容易被忽略的杀手。
♡ 0 人觉得有帮助
最后更新 25 天前
林 林亦然
资深后端工程师
评论 · 1