问题实战 Lock wait timeout exceeded try restarting transaction

背景:

项目对转账的功能进行优化,测试的时候,发现原转账功能无法使用。

mysql报错:

Statement cancelled due to timeout or client request

问题分析:

从字面意思来看是,预编译在等待执行或执行的时候,因为超时而取消了。

那么什么原因呢?

1.语句执行过慢

解决:

a.加索引

b.子查询尽量缩小搜索范围,减少join的次数

c.能用join就不要用in

d.加大查询时间 queryTimeOut

我们这边加大了queryTimeOut时间,然后报错:Lock wait timeout exceeded; try restarting transaction

通过排查,发现是在执行更新操作的时候,一直在等待锁。

select * from information_schema.innodb_trx;
select * from information_schema.innodb_locks;
select * from  information_schema.INNODB_LOCK_WAITS;
SELECT * from information_schema.`PROCESSLIST`;
SHOW FULL PROCESSLIST;

当发现一直在占用锁的事物锁,kill掉。
kill id

排查发现:占用的锁的语句,就是正在执行的更新语句。 这个是不对的。

继续排查,发现方法中使用了事物,该事务绑定的是sql连接池。

执行顺序是:

事物开始:

操作A进行了该行语句的更新

操作B(我的语句)执行该行语句的更新(该操作是自己建立的sql连接对象操作)

事物结束

这个时候,大家都发现问题了吧。

操作B必须要等到操作A事物提交,才能拿到行级锁。

修改:

方案1:

将操作B也使用sql连接池的连接,进行数据库操作

方案2:

将操作A进行修改,改成使用自己建立的sql连接来处理。

总结:

出现该问题的时候,肯定是有其它地方占用了锁,问题的解决点:需要先释放锁或者报错所有的操作,在同一个事物中。

 

 

你可能感兴趣的:(锁,事物)