innodb死锁1213 - Deadlock found when trying to get lock; try restarting transaction
问题背景:外网mysql在执行玩家保存数据的存储过程时,出现死锁 Deadlock found when trying to get lock; try restarting transaction
产生原因:两个线程AB提交事务时,对同一张表 test_deadlock(表名为化名)进行了如下操作:
A线程根据表主键进行插入更新(insert into ON DUPLICATE KEY UPDATE ),此时为行锁,
B线程对表进行删除部分数据(并不是根据主键),此时为表锁,
A线程对表进行删除部分数据(并不是根据主键),此时为表锁。此刻,B线程错误提示死锁。
重现过程:
CREATE TABLE `test_deadlock` ( `a` int(11) NOT NULL, `b` int(11) NOT NULL, `c` int(11) NOT NULL, PRIMARY KEY (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into `test_deadlock`(a,b,c) values(4,4,4) ON DUPLICATE KEY UPDATE b=4,c=4; insert into `test_deadlock`(a,b,c) values(3,3,3) ON DUPLICATE KEY UPDATE b=3,c=3; insert into `test_deadlock`(a,b,c) values(2,2,2) ON DUPLICATE KEY UPDATE b=2,c=2; insert into `test_deadlock`(a,b,c) values(1,1,1) ON DUPLICATE KEY UPDATE b=1,c=1;
用Navicate 工具,打开AB两个窗口,
A窗口执行:
start TRANSACTION;
insert into `test_deadlock`(a,b,c) values(1,1,1) ON DUPLICATE KEY UPDATE b=1,c=1;
B窗口执行:
update test_deadlock set b = 2 where b = 2;
A窗口执行:
update test_deadlock set b = 4 where b = 4; 此刻B窗口提示死锁。
以上想重复实验,请在A窗口执行:commit;
如何避免死锁:
1.使用事务,但是避免使用长事务,将大事务拆小,分段多提交。
2.sql语句条件是主键或者索引,这样执行后为行锁,避免表锁,从而避免死锁。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
2019-05-05 数据结构与算法之美,课后习题:06|链表(上):如何判断单链表回文字符串?