快速体验
- 打开 InsCode(快马)平台 https://www.inscode.net
- 输入框内输入如下内容:
创建一个MySQL锁等待问题的入门教学demo,要求:1. 用最简单SQL示例演示锁等待;2. 分步骤解释异常原因;3. 提供3种基础解决方案代码;4. 包含可视化流程图。使用PHP+MySQL实现,代码注释详细,适合新手学习。 - 点击'项目生成'按钮,等待项目生成完整后预览效果

最近在学习MySQL数据库时遇到了一个报错com.mysql.cj.jdbc.exceptions.mysqltransactionrollbackexception: lock wait timeout exceeded,查资料发现这是典型的锁等待超时问题。作为新手,我花了两天时间终于搞懂了原理和解决方法,这里把我的学习笔记分享给大家。
1. 什么是锁等待超时
简单来说,就是事务A占用了某条数据的锁,事务B也想修改这条数据,但等啊等,直到超过了MySQL设置的等待时间(默认50秒),就抛出这个异常。
2. 用SQL重现问题场景
假设我们有个简单的用户余额表,用以下SQL就能复现这个问题:
-
在第一个MySQL会话中执行:
(先不提交)BEGIN; UPDATE accounts SET balance = balance - 100 WHERE user_id = 1; -
然后在第二个会话中执行:
BEGIN; UPDATE accounts SET balance = balance + 50 WHERE user_id = 1;
这时第二个会话就会卡住,50秒后报锁等待超时错误。
3. 为什么会发生
- 第一个事务先获取了行锁
- 第二个事务想修改同一行,必须等待第一个事务释放锁
- MySQL默认最多等50秒(通过参数
innodb_lock_wait_timeout设置) - 超时后为避免长时间阻塞,自动回滚第二个事务
4. 三种基础解决方案
方案一:缩短事务长度
把大事务拆成小事务,尽快提交释放锁。比如:
-- 不好的做法(大事务)
BEGIN;
UPDATE 大量数据...
复杂计算...
COMMIT;
-- 改进做法
BEGIN;
UPDATE 部分数据...
COMMIT;
BEGIN;
UPDATE 其他数据...
COMMIT;
方案二:调整隔离级别
如果业务允许,可以改用READ COMMITTED隔离级别(默认是REPEATABLE READ):
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
注意:这可能会引起其他问题,需要评估业务需求。
方案三:增加等待时间
临时解决方案,适当增加等待超时时间(单位秒):
SET SESSION innodb_lock_wait_timeout = 100;
5. 实际开发建议
- 事务要尽量短小精悍
- 按相同顺序访问表,避免交叉等待
- 为高频查询添加合适索引
- 考虑使用乐观锁替代悲观锁
可视化流程
锁等待的基本流程可以这样表示:
事务A获取锁 → 事务B尝试获取锁 → 等待超时 → 事务B回滚
↑_______________|
遇到这个问题时,我用InsCode(快马)平台快速搭建了测试环境验证解决方案。这个平台可以直接在浏览器里运行MySQL和PHP代码,不需要本地安装环境,特别适合新手做技术验证。

他们的在线编辑器还能实时看到SQL执行效果,对我理解锁机制帮助很大。如果你也在学MySQL,不妨试试这种边做边学的体验方式。
快速体验
- 打开 InsCode(快马)平台 https://www.inscode.net
- 输入框内输入如下内容:
创建一个MySQL锁等待问题的入门教学demo,要求:1. 用最简单SQL示例演示锁等待;2. 分步骤解释异常原因;3. 提供3种基础解决方案代码;4. 包含可视化流程图。使用PHP+MySQL实现,代码注释详细,适合新手学习。 - 点击'项目生成'按钮,等待项目生成完整后预览效果
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
MySQL锁等待超时解决方案
1034

被折叠的 条评论
为什么被折叠?



