直接看SHOW ENGINE INNODB STATUS\G输出里的LATEST DETECTED DEADLOCK模块即可快速定位死锁根因;重点分析两个事务块中的HOLDS THE LOCK(S)与WAITING FOR THIS LOCK关系、锁类型(X/S、gap/record)、索引名及末尾SQL语句,结合时间戳、表名、行条件还原冲突链。

直接看 SHOW ENGINE INNODB STATUS\G 输出里的 LATEST DETECTED DEADLOCK 模块,就能快速定位死锁根因——关键不是“有没有日志”,而是“会不会读”。重点盯住三件事:事务执行顺序、锁的类型(X/S、gap/record)、被操作的具体资源路径(表名、索引名、行条件)。
怎么看懂死锁日志的关键字段
执行命令后,在输出中找到 LATEST DETECTED DEADLOCK 区域,它是一份结构清晰的“事故报告”:
-
时间戳:如
2026-08-20 14:15:22,可对齐 Java 应用日志,快速锁定业务上下文 -
两个事务块:分别标为
TRANSACTION 12345和TRANSACTION 67890,每块包含:-
HOLDS THE LOCK(S):已持有哪些锁(例如:X lock on index `PRIMARY` of table `db.order`, record id=1001) -
WAITING FOR THIS LOCK:正在等哪一把锁(例如:X lock on index `idx_user_id` of table `db.account`, where user_id = 2002) - 最后的 SQL 原文:如
UPDATE account SET balance = balance - 10 WHERE user_id = 2002,这是还原 Java 业务逻辑的核心线索
-
-
mysql tables in use和lock struct(s):判断是否误触全表锁或锁结构异常膨胀 -
WE ROLL BACK TRANSACTION XXX:MySQL 自动选中的牺牲者,但别只看这一行——它只是结果,不是原因
三步锁定根本原因
不要停留在“谁被回滚了”,要顺藤摸瓜还原冲突链:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
比对事务加锁顺序:事务 A 先锁
order再等account,事务 B 是否反过来先锁account再等order?这是最常见、修复成本最低的“访问顺序不一致” -
检查索引是否生效:若
WAITING FOR显示锁的是GEN_CLUST_INDEX或没带具体行值,大概率是 SQL 未命中索引,导致升级为表锁或间隙锁范围扩大 -
确认隔离级别影响:在
REPEATABLE READ下,SELECT ... FOR UPDATE或范围条件(如WHERE amount > 100)会隐式加间隙锁,可能把本不该锁的记录也圈进来
Java 侧快速落地的解决动作
数据库调优见效慢,代码层控制才是最快见效的手段:
立即学习“Java免费学习笔记(深入)”;
-
强制统一资源访问顺序:比如所有涉及账户和订单的操作,约定必须先按
user_id升序更新account表,再按order_id升序更新order表。可用工具类封装排序逻辑,避免人工出错 - 拆分长事务:把“查+校验+扣减+记日志+发消息”这种大事务,拆成原子粒度更小的事务。尤其把非核心操作(如日志落库、MQ 发送)移出主事务
-
开启全量死锁日志:在 MySQL 配置中设置
innodb_print_all_deadlocks = ON,配合错误日志轮转与监控埋点,实现死锁主动发现而非被动排查

















