生产异常 Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceed

本文详细介绍了在MySQL中遇到事务锁超时异常的情况,包括如何通过日志定位问题、查看未提交事务、手动执行更新语句等步骤。在生产环境中,为了解决客户紧急需求,采取了kill未提交事务的临时措施。同时,讨论了其他可能导致事务挂起的原因,如非数据库操作、异常处理不当和网络问题。提供的解决方案包括定期检查和手动处理挂起事务,确保数据库稳定运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、程序中报错日志:

Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: 
Lock wait timeout exceeded; try restarting transaction;
 Lock wait timeout exceeded; try restarting transaction; 
nested exception is com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: 
Lock wait timeout exceeded; try restarting transaction

grep "MySQLTransactionRollbackException"   *_2021-09-10.9.log

 查找第一次出现位置:grep -C 100 "MySQLTransactionRollbackException" 

 *_2021-09-10.9.log | head -201 


 

2、查看未提交事务:

select * from  information_schema.INNODB_TRX;

SELECT 
    a.id,a.user,a.host,b.trx_started,b.trx_query 
FROM information_schema.processlist a RIGHT OUTER JOIN information_schema.innodb_trx b
ON a.id = b.trx_mysql_thread_id;
 

3、手动执行该update语句,失败,等待锁超时:

update orders set *** where id='79302e18a8e848ccb2323c48ca4ca349';

update orders set *** where id='aeff09dbbc1a4668bf959f675d536ece';

4、由于是生产,客户急需处理业务数据,所以临时解决方案,是先kill 掉,未能提交事务的线程,

kill  trx_mysql_thread_id(上图中的trx_mysql_thread_id是10, 所以 执行  kill  10)

5、准备在测试环境复现这个问题,测试开启之前,查询是否有未提交事务

6、测试环境查看:

-- 查看正在锁的事务(没有)
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS; 

-- 查看等待锁的事务(没有)
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;

7、测试环境,制造未提交事务,把程序debug挂起:

 再次查看:show PROCESSLIST

执行查询未提交事务语句:select * from  information_schema.INNODB_TRX;

SELECT 
    a.id,a.user,a.host,b.trx_started,b.trx_query 
FROM information_schema.processlist a RIGHT OUTER JOIN information_schema.innodb_trx b
ON a.id = b.trx_mysql_thread_id;
 

如上只是其中一种事务挂起情况,目前的解决方案,就是手动kill掉长期挂起,未提交的事务。

还有其他原因,比如手动开启事务,发生异常的时候没有进行回滚操作,导致事务挂起;

再比如,开启事务以后,强行kill掉程序或者宕机,也会导致事务挂起。

其他情况,欢迎补充;

1、事务过程中执行其他非数据库操作,导致事务长期未被处理。
2、事务处理异常或实现逻辑有误,导致事务未被正常处理。
3、网段异常导致应用端请求未被正常发送给数据库,数据库等待应用后续操作。
4、应用服务器性能问题(如CPU爆满),导致应用无法及时切换到该进程进行处理。

参考帖:https://blog.youkuaiyun.com/weixin_39827589/article/details/113489406

MySQL Transaction--查看未提交事务执行的SQL - TeyGao - 博客园

https://segmentfault.com/a/1190000022442121

MySql Lock wait timeout exceeded该如何处理? - 凝雨 - Yun

### 解决 MySQLTransactionRollbackException 锁等待超时 当遇到 `com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: lock wait timeout exceeded` 的异常时,表明事务在尝试获取锁的过程中超过了设定的时间限制而被回滚。这通常发生在高并发场景下,多个事务竞争同一资源的情况。 #### 调整配置参数 可以通过调整 MySQL 配置文件中的 `innodb_lock_wait_timeout` 参数来增加默认的锁等待时间。该参数定义了 InnoDB 存储引擎在一个事务等待行级锁的最大秒数,默认通常是 50 秒。如果业务逻辑允许更长时间的等待,则可以适当提高这个值: ```sql SET GLOBAL innodb_lock_wait_timeout = 120; ``` 对于临时性的解决方案也可以通过会话级别设置此参数[^1]。 #### 分析并优化查询语句 分析引发冲突的具体 SQL 查询,并对其进行优化以减少锁定时间和范围。比如避免不必要的全表扫描操作;尽可能缩短持有排他锁的时间窗口;合理设计索引结构使得访问路径更加高效等措施均有助于缓解此类问题的发生频率。 #### 使用乐观锁机制替代悲观锁 传统的关系型数据库管理系统采用的是基于封锁协议实现的数据项控制方法——即所谓的“悲观”策略。而在某些应用场景里改用版本号或时间戳标记记录变化状态的方式(也就是常说的“乐观”并发控制),可以在一定程度上规避因频繁加解锁带来的性能瓶颈以及死锁风险。 #### 处理应用程序层面的竞争条件 检查应用层面上是否存在可能导致大量短连接快速建立又断开的情形,因为这种情况容易造成瞬时负载过高从而加剧争用状况。考虑引入缓存技术或者批量处理模式降低单位时间内提交给后台执行的任务量也是可行的办法之一。 #### 实施重试逻辑 考虑到偶尔发生的短暂性阻塞属于正常现象而非致命错误,因此建议客户端代码具备一定的容错能力,在捕获到上述特定类型的异常之后能够自动发起有限次数内的重复请求直至成功完成目标动作为止。 ```python import time from mysql.connector import Error, connect def execute_with_retry(query, max_retries=3): retries = 0 while True: try: connection = connect(host='localhost', database='testdb') cursor = connection.cursor() cursor.execute(query) break except Error as e: if 'lock wait timeout' not in str(e).lower(): raise retries += 1 if retries >= max_retries: raise Exception(f"Failed after {max_retries} retries.") sleep_duration = min(2 ** retries, 30) # Exponential backoff with cap at 30 seconds. print(f"Retrying ({retries}) due to lock wait timeout...") time.sleep(sleep_duration) execute_with_retry("UPDATE table SET column=value WHERE condition") ```
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值