生产环境的数据同步服务连续报了三件事:ERP 订单同步单个任务跑了 317 秒;任务执行期间,产品同步接口直接 Lock wait timeout(等锁 50 秒超时);再往前翻,还有一次 200 秒级别的死锁,innodb 状态转储里躺着 95 万行锁。三件事指向同一片代码,但三次现场的长尾耗时各不相同——130 秒、305 秒、317 秒,波动大得像玄学。
排查下来是两层问题叠在一起,彼此掩护:
- 代码里满屏的
@Async是个摆设——整个模块没有@EnableAsync,所有”异步任务”实际同步跑在 Tomcat 的 HTTP 请求线程里; - 一张 2000 行的小表没有二级索引,让一条多表 JOIN 的 UPDATE 走了全表锁定读,3000 行的批次锁了 9.3 万行。
最终修复只有两条 DDL 和一个配置类,本地实测单步耗时 48.9 秒 → 0.33 秒(约 150 倍),生产 7568 单全量同步从 317 秒回到 15.2 秒。这篇完整复盘两层问题的发现过程——尤其是中间那次”所有 EXPLAIN 都是毫秒级”的证据反转,差点让排查拐进死胡同。