Lock wait timeout exceeded; try restarting transaction的解决方案

一、 背景介绍

前段时间遇到一个锁超时的问题,错误日志如下:

出现这个问题的背景是:在全表同步的时候,为了提高效率,关闭了自动提交。

statementDelete = conn.prepareStatement(deleteSql.toString());
conn.setAutoCommit(false);

在业务逻辑处理完毕之后,没有手动提交,导致事物(在数据库代码中就是thread)一直处于running的状态。

在下一个任务要用到这个表时,发现之前的事物没哟提交,就会一直等待,然后报超时错误。

二、 解决方式

1. 由于这一块代码并不是我写的,即使是我写的,那么多行,可能也不能一下子就排查出来,所以就直接采用最舒适的方式,让数据库自己记录日志

(1)参考方式:通过修改配置文件,收集日志。

第32节:通过performance_schema获取造成死锁的事务语句 - 简书(本文由田兴椿编写) 数据库日常维护中我们经常遇到死锁的问题,由于无法获取造成死锁的事务内执行过的语句,对我们死锁的分析造成很大的困难。但是在MySQL 5.7中我们可以利用...https://www.jianshu.com/p/268889c997e8

在my.cnf中设置打开、关闭performance_schema选项随数据库启动

#设置setup_instruments表收集相关statement event
performance-schema-instrument='statement/%=ON'  
#开启events_statements_current表存储当前连接线程执行的最后一条statement event信息               
performance-schema-consumer-events-statements-current=ON   
#开启events-statements-history表默认存储每个线程最近10条statement event信息 
performance-schema-consumer-events-statements-history=ON        
#开启events-statements-history-long表默认存储最近10000条语句event信息
performance-schema-consumer-events-statements-history-long=ON   

performance-schema-consumer-statements-digest=ON       
         
#设置setup_instruments表收集transaction event
performance-schema-instrument='transaction=ON'    
#开启events_transactions_current表存储当前连接线程执行的transaction event信息              
performance-schema-consumer-events-transactions-current=ON      
#开启events_transactions_history表默认存储每个线程最近10条transaction event信息
performance-schema-consumer-events-transactions-history=ON   
#开启events_statements_history_long表默认存储最近10000条语句event信息。   
performance-schema-consumer-events-transactions-history-long=ON 

(2)通过命令的方式:


#设置是否开启日志
-- set global general_log=on;
#设置日志记录方式 table、file
-- set global log_output='table'

 2. 查询被锁的thread_id

具体可参考:https://blog.csdn.net/sunhuansheng/article/details/121907365

mysql 8之前的版本:information_schema

innodb_trx 当前运行的所有事务
innodb_locks 当前出现的锁
innodb_lock_waits 锁等待的对应关系
select * from information_schema.innodb_trx;
select * from information_schema.innodb_locks;
select * from information_schema.innodb_locks_waits;

mysql 8.0之后的版本:performance_schema

innodb_trx 当前运行的所有事务
innodb_locks 当前出现的锁
innodb_lock_waits 锁等待的对应关系
select * from information_schema.innodb_trx;
select * from performance_schema.data_locks;
select * from performance_schema.data_lock_waits;
 

通过

 select * from information_schema.innodb_trx; 

可知道,当前正在运行的thread_id是31:;

 因为该thread_id是事物未提交,处于running的状态,所以,

select * from information_schema.INNODB_LOCKS;
select * from information_schema.INNODB_LOCK_WAITS;

两个sql查无数据,没有明确的地方说是锁哪里的。

在命令界面,直接kill掉31;

 3. 重现问题

重现该问题,分析日志,查询到问题线程执行的sql语句。反过来去找代码中调用的地方。

SELECT *,CONVERT (argument USING utf8) as `sql` from mysql.general_log  where thread_id = 45 ORDER BY event_time DESC;

 结束。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值