mysql数据库死锁问题解决MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transact

博客记录了Spring事务提交时导致数据库事务无法释放,产生死锁并抛出操作超时异常的问题。推测可能是Spring事务嵌套所致,解决办法是在事务回滚注解中添加参数propagation = Propagation.REQUIRES_NEW 。

记录一下:

原因:spring事务提交时导致数据库事务得不到释放,产生死锁问题,紧接着抛出操作超时异常:MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction

有可能是因为spring的事务嵌套引起的问题,总之先解决眼前的问题,把mysql中产生死锁的事务进程干掉,所以记录一下sql

相关sql记录:

-- 查看数据库当前的进程
show processlist;
-- 当前运行的所有事务
SELECT * FROM information_schema.INNODB_LOCKs;
-- 当前出现的锁
SELECT * FROM information_schema.INNODB_LOCK_waits;
-- 锁等待的对应关系
SELECT * FROM information_schema.INNODB_TRX;
-- 查询产生锁的具体sql
select 
    a.trx_id 事务id ,
    a.trx_mysql_thread_id 事务线程id,
    a.trx_query 事务sql 
from 
    INFORMATION_SCHEMA.INNODB_LOCKS b,
    INFORMATION_SCHEMA.innodb_trx a 
where 
    b.lock_trx_id=a.trx_id;
-- 		!!!
select concat('KILL ',a.trx_mysql_thread_id ,';') 
	from INFORMATION_SCHEMA.INNODB_LOCKS b,INFORMATION_SCHEMA.innodb_trx a 
	where b.lock_trx_id=a.trx_id;
-- 杀掉死锁进程
kill {thread_id};

解决:

在事务回滚注解中添加参数:propagation = Propagation.REQUIRES_NEW(默认为:Propagation.REQUIRED)

@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    ResponseData updateBath(List<Entity> entity) throws ParseException;
### 三级标题:MySQL事务回滚异常:锁等待超时的解决方案 MySQL中出现`Lock wait timeout exceeded; try restarting transaction`异常通常是由于事务在等待锁资源时超过了系统设定的超时时间(默认为50秒)[^3]。这种问题通常发生在并发事务较多的场景下,尤其是在高并发或事务执行时间较长的情况下。以下是对该问题的详细分析和解决方案。 #### 优化事务执行时间 事务执行时间过长是导致锁等待超时的主要原因之一。长时间运行的事务会持续持有锁资源,从而阻塞其他事务的执行。因此,优化SQL语句、减少事务处理时间是解决问题的关键。可以通过以下方式优化事务: - **减少事务中的操作数量**:避免在一个事务中执行大量的数据更新、插入或删除操作。 - **使用索引**:确保查询语句使用了合适的索引,避免全表扫描,从而减少锁定的行数。 - **拆分事务**:将一个大事务拆分为多个小事务,减少每个事务持有锁的时间。 #### 检查未提交的事务 如果事务未及时提交或回滚,会导致锁资源无法释放,从而影响其他事务的操作。可以通过以下方式排查和解决: - **检查长时间未提交的事务**:使用`SHOW ENGINE INNODB STATUS`命令查看当前正在运行的事务及其持有的锁资源。 - **设置合理的事务超时时间**:通过`innodb_lock_wait_timeout`参数调整事务等待锁的最长时间,默认为50秒,可以根据业务需求适当调整[^3]。 #### 避免死锁 死锁是多个事务相互等待对方释放锁资源而导致的系统僵持状态。MySQL的InnoDB引擎具备死锁检测机制,会自动回滚其中一个事务以打破死锁。可以通过以下方式减少死锁的发生: - **统一访问顺序**:确保多个事务按照相同的顺序访问表和行。 - **减少事务的持有锁时间**:尽量在事务中尽早提交,减少锁的持有时间。 #### 检查连接池配置 在某些情况下,连接池配置不当也可能导致事务异常。例如引用中提到`interactive_timeout`为120秒,而连接池的`maxIdleTime`设置为10000秒,这可能导致连接池中的连接在MySQL服务器端被断开,但连接池仍然认为连接有效,从而导致事务异常[^4]。因此,应确保连接池的配置与MySQL服务器的配置匹配: - **调整连接池的空闲超时时间**:确保连接池的`maxIdleTime`不超过MySQL的`wait_timeout`或`interactive_timeout`值。 - **启用连接验证机制**:例如在使用C3P0连接池时,可以配置`testConnectionOnCheckin`或`testConnectionOnCheckout`参数,确保连接在使用前是有效的。 #### 代码层面的优化 在应用程序代码中,确保事务的正确提交或回滚是避免锁等待超时的重要手段: - **显式提交事务**:在事务执行完成后,确保调用`commit()`方法提交事务。 - **异常处理中回滚事务**:在捕获到异常时,确保调用`rollback()`方法回滚事务,释放锁资源。 - **使用try-with-resources**:在Java中使用JDBC 4.1及以上版本时,可以使用try-with-resources语句块自动管理事务的提交和回滚。 #### 示例代码:Java中事务的正确提交与回滚 ```java try (Connection conn = dataSource.getConnection(); PreparedStatement ps = conn.prepareStatement("UPDATE users SET balance = ? WHERE id = ?")) { conn.setAutoCommit(false); // 开启事务 ps.setDouble(1, 100.0); ps.setInt(2, 1); ps.executeUpdate(); conn.commit(); // 提交事务 } catch (SQLException e) { if (conn != null) { conn.rollback(); // 回滚事务 } e.printStackTrace(); } ``` ### 相关问题 1. 如何通过`SHOW ENGINE INNODB STATUS`分析事务锁信息? 2. MySQL中如何调整`innodb_lock_wait_timeout`参数? 3. 如何在Java中使用C3P0连接池时避免因连接超时导致的事务异常? 4. 如何判断一个事务是否持有过多锁资源? 5. 什么是死锁MySQL如何自动处理死锁
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值