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

本文详细解析了遇到的MySQL锁等待超时错误(ERROR 1205),介绍了如何通过调整innodb_lock_wait_timeout参数来解决此问题,包括参数的作用、默认值及调整方法。

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

今天程序里报的错: java.sql.BatchUpdateException: Lock wait timeout exceeded; try restarting transaction,重启服务后也没有效果,然后查看mysql官方文档如下:

Error: 1205 SQLSTATE: HY000 (ER_LOCK_WAIT_TIMEOUT)
Message: Lock wait timeout exceeded; try restarting transaction
InnoDB reports this error when lock wait timeout expires. The statement that waited too long was rolled back (not the entiretransaction). You can increase the value of the innodb_lock_wait_timeout configuration option if SQL statements should wait longer for other transactions to complete, or decrease it if too many long-running transactions are causing locking problems and reducing concurrency on a busy system.

翻译如下:
当锁等待超时后innodb引擎报此错误,等待时间过长的语句被回滚(不是整个事务)。如果想让SQL语句等待其他事务更长时间之后完成,你可以增加参数innodb_lock_wait_timeout配置的值。如果有太多长时间运行的有锁的事务,你可以减小这个innodb_lock_wait_timeout的值,在特别繁忙的系统,你可以减小并发。
The length of time in seconds an InnoDB transaction waits for a row lock before giving up. The default value is 50 seconds. A transaction that tries to access a row that is locked by another InnoDB transaction waits at most this many seconds for write access to the row before issuing the following error:
ERROR 1205 (HY000):Lock wait timeout exceeded; try restarting transaction
InnoDB事务等待一个行级锁的时间最长时间(单位是秒),超过这个时间就会放弃。默认值是50秒。一个事务A试图访问一行数据,但是这行数据正在被另一个innodb事务B锁定,此时事务A就会等待事务B释放锁,等待超过innodb_lock_wait_timeout设置的值就会报错ERROR 1205 (HY000):

于是我尝试调大innodb_lock_wait_timeout参数:
具体操作:如下可知innodb_lock_wait_timeout是动态参数,默认值50秒,最小值是1秒,最大值是1073741824;

mysql> set GLOBAL innodb_lock_wait_timeout=1500;
(题外话:关于setinnodb_lock_wait_timeout=1500; 和 set global innodb_lock_wait_timeout=1500;的区别。前者等价于set session只影响当前session,后者作为全局的修改方式,只会影响修改之后打开的session;注意后者不能改变当前session;)

问题解决

### MySQL 更新时出现锁等待超时问题的解决方案 当遇到 `Lock wait timeout exceeded; try restarting transaction` 的错误时,这通常表明当前事务因长时间未能获取到所需的资源锁而被回滚。以下是针对该问题的具体分析和解决方案: #### 1. 背景描述 此错误通常是由于多个并发事务争夺同一资源而导致的锁定冲突引起的[^3]。具体表现为某个事务试图修改已被另一个未提交事务占用的数据。 --- #### 2. 原因分析 - **长事务持有锁**:某些事务运行时间过长,在其完成之前阻止了其他事务对该数据的操作。 - **死锁情况**:两个或更多事务相互依赖对方持有的锁,形成循环等待。 - **高并发环境下的竞争**:在高并发场景下,频繁读写相同记录可能导致锁争用加剧。 - **配置参数不足**:默认情况下,InnoDB 存储引擎中的 `innodb_lock_wait_timeout` 参数设置为较低值(如 50 秒),可能不足以满足复杂业务需求[^3]。 --- #### 3. 解决方案 ##### 3.1 查询并终止阻塞事务 通过查看当前活动会话及其状态来定位哪个事务正在占用所需资源,并考虑手动中断它以释放锁: ```sql -- 查看所有进程列表 SHOW PROCESSLIST; -- 杀掉指定 ID 的线程 KILL <thread_id>; ``` 如果发现某条语句执行时间异常延长,则可能是造成堵塞的原因之一[^3]。 ##### 3.2 扩展锁等待超时时限 调整 InnoDB 默认锁等待时限可以给事务更多的机会去获得必要的锁而不至于立即失败。可以通过修改全局变量实现这一点: ```sql SET GLOBAL innodb_lock_wait_timeout = 120; ``` 注意重启服务可能会恢复原始设定,因此建议将其加入 my.cnf 配置文件永久生效[^3]: ```ini [mysqld] innodb_lock_wait_timeout=120 ``` ##### 3.3 优化 SQL 逻辑减少锁范围及时长 重新审视涉及更新操作的相关代码片段,确保它们遵循最佳实践原则,比如只加载必要字段而非整张表扫描;利用索引加速检索过程从而缩短加锁周期等等[^4]。例如对于批量处理任务来说,分批次提交而不是一次性全部做完往往能有效缓解压力。 ##### 3.4 使用乐观锁机制替代悲观锁策略 传统方式采用显式的行级排他锁控制访问权限容易引发此类问题,转而应用版本号验证方法可以在一定程度上规避这些问题的发生几率[^5]。即每次变更前先校验目标对象最新版本号是否匹配预期值,如果不符则提示用户刷新页面后再试。 --- ### 示例代码展示如何增加锁等待时间 下面是一个简单的例子说明怎样动态改变 session 层面的锁等待阈值以便临时解决问题: ```sql -- 设置当前连接内的锁等待时间为 300 秒 SET SESSION innodb_lock_wait_timeout = 300; -- 尝试再次执行原来失败的 DML 操作 DELETE FROM facebook_posts WHERE id = 7048962; ``` ---
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值