TransactionTimedOut异常根源是MySQL事务锁等待未释放,需查INNODB_TRX中TRX_STATE='RUNNING'且TRX_STARTED异常早的事务,再通过INNODB_LOCK_WAITS定位阻塞者,KILL blocking_thread而非报错线程,并修复Java事务超时配置与异常处理缺陷。

TransactionTimedOut 异常(如 TransactionTimedOutException: deadline was ...)在 Java 应用中常被误判为数据库连接超时或网络问题,但实际根源往往是 MySQL 事务锁等待未被及时释放——它和 Lock wait timeout exceeded 同源,只是上层框架(如 Spring、iBatis)做了不同封装。直接查锁,别查连接池。
查 INNODB_TRX 找出“卡住不动”的 RUNNING 事务
真正阻塞别人的不是报错线程,而是那个长时间 TRX_STATE = 'RUNNING' 却没提交的事务。它可能卡在应用层远程调用、空循环、未捕获异常后的漏提交等场景。
-
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TRX_STATE = 'RUNNING' ORDER BY TRX_STARTED;—— 重点关注TRX_STARTED时间远早于当前时间(比如几十分钟前)的记录 - 检查
TRX_QUERY是否为空(说明 SQL 已执行完,但事务没结束),或是否是明显耗时操作(如大 UPDATE + 子查询) - 注意
TRX_MYSQL_THREAD_ID,这是后续KILL的目标 ID,不是报错日志里那个线程号
用 INNODB_LOCK_WAITS 关联等待与持有关系
单看 INNODB_TRX 只能知道谁“活着”,但不知道谁在等谁。必须结合 INNODB_LOCK_WAITS 确认阻塞链。
- 执行标准关联查询(务必用
INNER JOIN,避免遗漏):SELECT t1.TRX_ID waiting_trx_id, t1.TRX_MYSQL_THREAD_ID waiting_thread, t1.TRX_QUERY waiting_query, t2.TRX_ID blocking_trx_id, t2.TRX_MYSQL_THREAD_ID blocking_thread, t2.TRX_QUERY blocking_query FROM INFORMATION_SCHEMA.INNODB_TRX t1 INNER JOIN INFORMATION_SCHEMA.INNODB_LOCK_WAITS w ON t1.TRX_ID = w.BLOCKING_TRX_ID INNER JOIN INFORMATION_SCHEMA.INNODB_TRX t2 ON w.BLOCKING_TRX_ID = t2.TRX_ID;
- 如果查不到结果,不代表没锁:可能是锁刚释放、或是死锁已被 InnoDB 自动回滚(此时日志会有
Deadlock found) -
t2.TRX_QUERY为空且t2.TRX_STATE = 'RUNNING',基本可断定是应用层事务未正常退出
KILL blocking_thread 而非 waiting_thread
杀错线程毫无意义:报错线程(waiting_thread)只是失败者,它一死,下一个请求立刻复现同样问题。必须终结源头。
立即学习“Java免费学习笔记(深入)”;
- 确认
t2.TRX_STATE = 'RUNNING'后,执行KILL <code>t2.TRX_MYSQL_THREAD_ID; - 执行前快速检查该线程是否还在干活:
SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = <code>t2.TRX_MYSQL_THREAD_ID;,若STATE是NULL或Waiting for table metadata lock,更应果断 KILL - 不要依赖
SHOW PROCESSLIST查锁——它不展示锁等待关系,容易漏掉真正持锁者
Java 层事务配置与代码缺陷排查点
MySQL 锁只是表象,根因在 Java 事务边界失控。常见硬伤包括:
- @Transactional 缺少
timeout参数,导致事务默认无限期挂起;应显式设为timeout = 30(单位秒) - 事务方法内调用了含远程 HTTP/RPC 的逻辑,且未做超时控制,整个事务被卡住
- try-catch 吞掉了异常,导致
@Transactional无法触发 rollback,事务悬而未决 - 嵌套事务使用
REQUIRES_NEW时,外层事务未提交前,子事务更新同一行会直接锁等待(典型“事务嵌套锁冲突”) - 批量操作未分页,一次 UPDATE 影响数万行,行锁升级为间隙锁甚至表级影响,大幅增加等待概率
锁等待超时的本质是事务生命周期管理失控,MySQL 只是暴露问题的镜子。查锁要快准狠,修代码要盯住事务入口和异常出口——尤其那些“看起来不会出错”的远程调用和循环逻辑。


















