1. 当你的MySQL突然“卡住”:理解Lock wait timeout
那天下午,系统监控突然开始报警,业务群里炸开了锅:“订单页面怎么一直在转圈圈?”“下单提交不了,提示系统繁忙!”我赶紧登录服务器查看日志,满屏都是刺眼的红色错误:
Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
这个错误,相信很多后端开发都遇到过。简单来说,就是你的SQL语句在等待一个“锁”的时候,等得太久了,MySQL不耐烦了,直接给你抛了个异常。这就像你去银行柜台办业务,前面有个人一直占着窗口磨磨蹭蹭,你等了50秒(MySQL默认的超时时间)还没轮到你,保安(MySQL)就过来请你出去了,让你“重启事务”(try restarting transaction)。
但问题来了,这个“锁”是谁占着的?为什么它一直不释放?在生产环境,这可不是小事,直接关系到用户能不能下单、支付能不能成功。我遇到过最极端的情况,一个锁等待导致整个订单系统瘫痪了半小时,损失惨重。所以,今天我就把自己这些年排查这类问题的经验,从最紧急的线上救火,到深度的根因分析,再到如何预防,完整地分享给你。你不用死记硬背那些复杂的命令,跟着我的思路,像破案一样,一步步找到那个“占着茅坑不拉屎”的事务。
2. 紧急止血:5分钟定位并Kill阻塞事务
线上系统告警,第一要务是恢复,而不是排查。这时候,你需要一套最快、最准的“组合拳”。别慌,跟着我做。
第一步:找到罪魁祸首——那个长时间运行的事务
直接上核心命令,连接上你的MySQL数据库(生产环境记得用只读账号或者从库),执行:
SELECT
trx.trx_id AS 事务ID,
trx.trx_state AS 事务状态,
trx.trx_started AS 事务开始时间,
trx.trx_mysql_thread_id AS 线程ID,
trx.trx_query AS 正在执行的SQL,
pl.USER AS 连接用户,
pl.HOST AS 连接来源,
TIME_TO_SEC(TIMEDIFF(NOW(), trx.trx_started)) AS 已运行秒数
FROM
information_schema.INNODB_TRX trx
LEFT JOIN
information_schema.PROCESSLIST pl
ON
trx.trx_mysql_thread_id = pl.ID
WHERE
trx.trx_state = 'RUNNING'
ORDER BY
trx.trx_started ASC;
这条命令是我排查问题的起点。INNODB_TRX 这个表是InnoDB引擎的心脏,记录了所有正在进行的事务。我们关联 PROCESSLIST 是为了看到更直观的连接信息。重点看哪些

2万+

被折叠的 条评论
为什么被折叠?



