
今天给大家分享一次生产环境的真实巡检故障:大量锁等待超时,排查后发现竟是trx_mysql_thread_id=0的事务在搞鬼,kill命令完全失效,最后靠XA事务回滚才解决。
这种问题隐蔽性极强,常规排查思路完全失效,看完这篇,下次遇到直接照抄解决方案!
一、问题现象:批量锁等待超时,业务更新失败
日常巡检数据库时,日志里疯狂报错:
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
手动执行业务更新SQL,同样触发报错:
UPDATE tbname SET column_name = 2
WHERE col_id= '25945fa285904ea59cd92a73a3850ceb' AND aYear = 2018 AND aMonth = 5;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction典型的锁等待超时,业务更新被阻塞,影响正常运行。
二、排查过程:常规思路全失效,发现诡异事务
遇到锁等待,第一反应是查活跃会话、查未提交事务,结果全程踩坑:
1. 排查活跃会话
先查正在运行的SQL,完全没有对该表的操作:
select * from information_schema.processlist where info is not null;2. 排查InnoDB事务
接着查INNODB_TRX,果然有大量未提交事务,本以为找到元凶,准备kill会话:
SELECT * FROM information_schema.INNODB_TRX;
结果中确实存在大量事务,此时原本以为已经查到问题,直接将对应为提交的事务杀掉即可(已与相关人员确认可以杀),于是把脚本准备好,准备大开杀戒。
3. 核心卡点:trx_mysql_thread_id=0
拼接kill语句时直接傻眼:所有事务的trx_mysql_thread_id全部为0!
SELECT concat('kill ',trx_mysql_thread_id,";") t_sql FROM information_schema.INNODB_TRX;kill 0完全无效,这根本不是普通的用户会话事务!
最终确认:trx_mysql_thread_id=0的事务,全部是MySQL XA分布式事务。
三、处理方案:XA事务专用回滚步骤
普通kill命令失效,必须用XA事务语法手动回滚,步骤直接复制可用:
1. 查看未处理的XA事务
执行xa recover,列出所有prepare状态的XA事务:
mysql> xa recover;
+------------+--------------+--------------+-------------------------------+
| formatID | gtrid_length | bqual_length | data |
+------------+--------------+--------------+-------------------------------+
| 1096044365 | 20 | 9 | tm156393736565426841tm1333009 |
| 1096044365 | 20 | 9 | tm156393708714926372tm1332251 |
+------------+--------------+--------------+-------------------------------+2. 拼接XA回滚语句
XA回滚固定格式:
xa rollback 'gtrid内容','bqual内容',formatID;拆分规则:
以上面数据为例,拼接结果:
xa rollback 'tm156393736565426841','tm1333009',1096044365;3. 批量执行回滚
逐行执行回滚语句,清理所有僵死XA事务:
mysql> xa rollback 'tm156393736565426841','tm1333009', 1096044365;
Query OK, 0 rows affected (0.00 sec)
4. 验证结果
再次查询INNODB_TRX,无残留事务

重新执行业务更新SQL,执行成功,锁等待超时错误彻底消失,业务恢复正常。

四、XA分布式事务到底是什么?
本次问题出在分库分表场景,业务跨多个库操作,必须用分布式事务保证一致性,而MySQL的XA事务就是基于两阶段提交(2PC)实现的。
1. 两阶段提交流程

2. MySQL XA事务基础语法
-- 开启XA事务
XA START 'xatest';
-- 执行业务SQL
INSERT INTO mytable (i) VALUES(10);
-- 结束XA事务
XA END 'xatest';
-- 准备阶段(核心:会持有锁)
XA PREPARE 'xatest';
-- 提交/回滚
XA COMMIT 'xatest';
XA ROLLBACK 'xatest';3. XA事务的致命问题
XA事务有如下几个主要问题:
4. 避坑建议
生产环境可以禁用XA事务,如果没禁用,建议经常进行巡检及监控,即从如下方面进行:
五、总结
trx_mysql_thread_id=0是MySQL分布式事务的标志性特征,遇到锁等待超时先查这个字段,别盲目kill会话!解决方案是:xa recover查看→拆分gtrid/bqual→xa rollback回滚,这样才能解决僵死XA事务导致的锁阻塞。
你在生产中遇到过哪些诡异的MySQL锁问题?欢迎评论区留言交流~
觉得干货实用,记得点赞、在看、转发,关注我,持续分享MySQL实战排坑技巧!