4.2 锁冲突矩阵
简单版矩阵

文章插图
当我们将gap lock(间隙锁), next key lock(next-key锁), Insert Intention lock(插入意向锁)也加入矩阵时 , 就会复杂很多了

文章插图
说明:
- not gap: 行锁
- gap: gap lock
- next-key: gap + 行锁
针对上面的矩阵 , 理解下面几个原则即可推导上面矩阵
- gap lock只会与插入意向锁冲突
- X行锁会与行锁冲突
- next key lock: 行锁 + gap锁 锁区间内 , 插入冲突; 行锁的X锁冲突
- 并发插入相同记录导致死锁
创建一个最简单最基础的表 , 用于演示
CREATE TABLE `t` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;INSERT INTO `t` (`id`) VALUES (1);1. 事务回滚的死锁问题场景复现:
step1:
-- session1: begin; insert into t values (2);-- session2:begin; insert into t values (2);-- 阻塞-- session3:begin; insert into t values (2);-- 阻塞step2:-- session1:rollback;
文章插图
原因分析:
死锁日志查看
SHOW ENGINE INNODB STATUS;
文章插图
step1:
- session1: 插入(id=2) , 会添加一个X + Next Lock锁
- session2/3: 插入(id=2) , 插入意向锁被阻塞 , 改为持有S + Next Lock锁
- session1: 回滚 , 释放X锁
- session2/3: 竞争X锁 , 只有对方释放S锁 , 才能竞争成功;相互等待 , 导致死锁
和前面操作基本一致 , 只是第一个会话是删除记录
step1:
-- session1: begin; delete from t where id=1;-- session2:begin; insert into t values (1);-- 阻塞-- session3:begin; insert into t values (1);-- 阻塞step2:-- session1:commit;
文章插图
原因分析和前面基本一致

文章插图
3. insert加锁逻辑
insert中对唯一索引的加锁逻辑
- 先做UK冲突检测 , 如果存在目标行 , 先对目标行加S Next Key Lock(该记录在等待期间被其他事务删除 , 此锁被同时删除)
- 如果1成功 , 对对应行加X + 插入意向锁
- 如果2成功 , 插入记录 , 并对记录加X + 行锁(有可能是隐式锁)
step1:
-- session1begin; delete from t where id = 1;-- session2begin; delete from t where id = 1;step2:-- session1insert into t values(1)
文章插图
对应的死锁日志

文章插图
关于这个场景详情博文可以参考:记录一次Mysql死锁排查过程
4. 怎么避免死锁呢?
- 将大事务拆成小事务
- 添加合理的索引 , 走索引避免为每一行加锁 , 降低死锁的概率
- 避免业务上的循环等待(如加分布式锁之类的)
- 降低事务隔离级别(如RR -> RC 当然不建议这么干)
- 并发插入时使用replace/on duplicate也可以避免死锁
作者:一灰灰
链接:https://juejin.cn/post/6927197371227095047
来源:掘金
推荐阅读
- JS排序算法:冒泡、选择、插入、归并、快速、希尔、堆、计数
- 清朝男人为什么梳辫子 清朝男人辫子多久洗一次
- |钓一次鱼要用十几斤玉米?野钓翘嘴鱼窝料不在多,打窝节奏很关键
- 汽车刹车片多久换一次才是最安全
- 一次不经意的相遇,让我们?今天是我们相识的第100天
- 2.春种一粒粟?种一粒粟春种一粒粟
- Mybatis 批量插入万条数据
- 高并发服务遇Redis瓶颈引发的事故
- 一次难忘的滑雪经历?滑雪场的奇妙邂逅
- 最早出使西域为开辟丝绸之路做出贡献的是谁 张第一次出使西域的主要目的是什么
