Administrator
Administrator
发布于 2024-10-22 / 51 阅读
0
0

记一次MySQL锁等待超时问题处理

lock wait timeout exceeded; try restarting transaction!

背景

今天群消息忽然炸了!说是全域CRM下单时,一旦选择X5pro机型创建订单行时,就一直转圈圈,等待很久后弹窗报错:

还有业务反应,订单表导入时,一两条也会报错,报错信息也是: SQL错误[1205] [40001]: Lock wait timeout exceeded; try restarting transaction` 。而且订单模块页面也很卡!

调查

报错日志给的很清楚:com,mysql.cj,jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction ,而且结合后面的 INSERT INTO lnk_sale_order_item (row id, ... 很明显就是:锁等待超时——往数据库lnk_sale_order_item表插入数据时发生了锁等待超时。

那这个插入语句为什么会出现锁等待超时呢?这个insert语句事务(A)在等什么锁,又是别的什么事务(B)一直占用了这个锁呢?

mysql 什么锁,可能会导致其它事务的insert语句被阻塞?回顾下mysql锁类型不难得到答案:

  • 记录锁:如果事务B正在执行insert或update但是一直没提交,而事务A执行的insert语句试图插入冲突的唯一键或主键,将被阻塞,直到B提交后,A才会报唯一键冲突!而如果B执行时间太长,A就会因为等待行锁超过mysql设置值(默认50s) 从而报错锁等待超时!

  • 间隙锁:如果事务B正在更新某个范围的数据却一直没提交,而事务A要插入的数据正好处于这个范围,那么也会导致事务A等待间隙锁超时!

  • 临键锁:如果事务B正在更新某个范围的数据却一直没提交, 则既不能在这个范围内新插入数据,也不能更改这个范围的数据,如果事务A正好是要在这个范围插入或者更改数据,则可能导致等待临键锁超时!

  • 表锁:lnk_sale_order_item表被锁定。当发生较为严重的死锁、资源耗尽等情况时,InnoDB可能会锁表。

  • 元数据锁(MDL):当事务B在执行DDL语句时,会对整个表加上MDL锁,如果事务B一直不提交,那么其它事务对当前表的CRUD操作都会被阻塞。就可能导致锁等待超时!

结合上面的分析,可以在案发现场时,看看数据库事务信息和锁的情况:

-- 当前在InnoDB内部执行的所有事务信息, 包含事务是否在等待锁,事务何时开始以及事务正在执行的SQL语句
select * from information_schema.INNODB_TRX; 
-- 当前出现的锁
select * from information_schema.INNODB_LOCK_WAITS; 
-- 锁等待的对应关系
select * from information_schema.INNODB_LOCKS; 

由于此篇是后记,案发现场已经没了,这里没办法把当时上述sql查询的结果贴出来。

我们可以通过上述sql定位到占用锁的事务,找到其线程id, kill 掉。但这只能是临时解决办法,关键还是需要找到程序中的事务B, 排查其占用锁时间过长的原因。

为解线上燃眉之急,当时立刻重启系统,但业务发现,重启之后过不了多久创建订单行时还是会卡死,然后报上述错误。但有一个新的发现:如果下单的物料是x5pro,则会一直转圈,然后其它的物料下单也慢,也会影响其他人下单。重启后如果不选x5pro,那么问题就不存在。

猜想,可能是选择X5Pro后走了某个逻辑,这个逻辑里八成含有慢查询,导致事务耗时太久。通过代码逐行翻阅,发现果然X5Pro这个物料在下单时会触发一个政策匹配逻辑,其中含有2个慢查询,在查询语句中嵌套了 EXISTS,而且涉及的是数据量较大的订单头表和订单行表,sql执行时间可能达到4、5分钟!

解决

将这两个慢查询EXISTS改通过LEFT JOIN达到同样的效果,重新发布后问题得到解决。

追问?

1.在上面的分析过程中,定位到问题的转折点是“下单下X5Pro就会导致卡顿”,从而通过程序代码定位到慢查询。如何直接从mysql中查询出慢查询呢?

可以通过上面提到的sql语句进行分析!后面专文分析。

2.虽然最后通过慢查询定位到了持续占锁的事务代码,但还有一个问题没有追究到底——这个事务到底占用的是什么锁?

由于现场不在,而且复现需要一定的并发量,测试环境不好满足。这个问题可以通过 SHOW ENGINE INNODB STATUS 语句进行分析。

引用


评论