我的编程空间,编程开发者的网络收藏夹
学习永远不晚

【MySQL】MySQL gap lock产生时机

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

【MySQL】MySQL gap lock产生时机

1)提出问题:我们通常说在Repeate read下面,会有next-key lock(LOCK_ORDINARY)对应值0,而READ COMMITTED隔离级别下只会有记录锁LOCK_REC_NOT_GAP(对应值1024),那么什么时候会有gap lock(LOCK_GAP)对应值512?


2)官方的一个死锁例子(之所以会选这个例子,是因为这个例子非常典型,为了更好的效果,我将隔离级别设置为READ COMMITTED):

    创建表并插入数据
    CREATE TABLE `locktest6` (   `id` int(11) NOT NULL,   `a` int(11) NOT NULL,   `b` varchar(30) NOT NULL DEFAULT 'xddd',   PRIMARY KEY (`id`),   UNIQUE KEY `a` (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

    INSERT INTO `locktest6` VALUES (3,2,'xddd'),(9,20,'ddd'),(12,13,'ddd'),(19,7,'cccc'),(20,5,'abcd'),(21,4,'fff');

    开启三个会话,会话的顺序是(1->2->3)
    session 1:
    【MySQL】MySQL gap lock产生时机



    session 2:
    【MySQL】MySQL gap lock产生时机

    session 3
    

    实验现象,这里session2、session3会阻塞(这里读者可以自己实验)

    现象分析:
    我们来看阻塞时的锁获取与等待情况
                            


这里唯一键a=17的二级索引加了LOCK_X|LOCK_REC_NOT_GAP|LOCK_REC锁,其次这条记录上面还有两把锁(LOCK_S|LOCK_ORDINARY|LOCK_WAITTING)在等待,分别是session2与session3的

这里的原因是:
session 1的insert 本来不加锁(是隐式锁,隐式锁是一种延迟加锁的策略);

当session插入a=17的记录时,发现与session1重复,这时session2会给session1加锁,锁为LOCK_X|LOCK_REC_NOT_GAP|LOCK_REC,同时把自己置为等待状态LOCK_S|LOCK_ORDINARY|LOCK_WAITTING,注意,这里为什么自己(session2)等待的时候是LOCK_S而不是LOCK_X呢,其实是为了提高并发;

session 3处于等待是因为session1 a=17的记录已经被session2加上了LOCK_X|LOCK_REC_NOT_GAP|LOCK_REC锁,而session3的a=17与session1的a=17重复,为了检测唯一性,也会将自己置为等待状态,锁为LOCK_S|LOCK_ORDINARY|LOCK_WAITTING


回滚session1,session3会成为死锁牺牲品,session2插入成功

session2

session3

【MySQL】MySQL gap lock产生时机


这是的死锁情况以及加锁情况
【MySQL】MySQL gap lock产生时机
这里锁信息连到了一起,哈哈,如何解释呢,我们稍后分晓


先分析上面的死锁:
session 1 rollback后,二级索引记录为(33,17)的记录的被删除,上面的session2,session3上的LOCK_S|LOCK_ORDINARY|LOCK_WAITTING将他的gap锁分别迁移到下一条记录,即二级索引(20,9)的记录上由两把锁,分别为session2与session占有,锁为LOCK_S|LOCK_GAP|LOCK_REC,即死锁图中的lock mode s lock gap before rec;与此同时,session 2与session3在插入的时候,还要检测下一条记录上(即(20,9)的记录上)的锁是否与LOCK_X|LOCK_GAP|LOCK_INTENSION冲突,这样就形成了session2的LOCK_X|LOCK_GAP|LOCK_INTENSION在等待session3 的LOCK_S|LOCK_GAP|LOCK_REC释放,而session3的LOCK_X|LOCK_GAP|LOCK_INTENSION则在等待session2的LOCK_S|LOCK_GAP|LOCK_REC释放,这样就形成了死锁,这里事务选择回滚了session3

再分析session2的加锁情况:
session3回滚后 ,session2获得了LOCK_X|LOCK_GAP|LOCK_INTENSION锁与LOCK_S|LOCK_GAP|LOCK_REC,这个锁加在记录(20,9)上;heap no 8的记录即session2插入的记录也获得了LOCK_S|LOCK_GAP|LOCK_REC锁,这是因为插入时,会进行锁分裂,将heap no 8下一条记录的(20,9)的锁LOCK_S|LOCK_GAP|LOCK_REC迁移到了heap no 8的记录上;为啥上面的锁信息会连在一起呢,即既有LOCK_S|LOCK_ORDINARY|LOCK_REC又有LOCK_S|LOCK_GAP|LOCK_REC呢,答案是:这里的LOCK_S|LOCK_ORDINARY|LOCK_REC只是表示下面行LOCK_S|LOCK_GAP|LOCK_REC有LOCK_S|LOCK_ORDINARY|LOCK_REC继承而来,并不表示记录上还加了LOCK_S|LOCK_ORDINARY|LOCK_REC锁


3)总结
    gap锁一般很少见到,当唯一索引检测重复的值的时候,往往会产生gap锁;另外当可重复读隔离级别下,做等值查询时,也会碰到gap锁(这个读者可以自己去实验),时间仓促,没有整理。


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

【MySQL】MySQL gap lock产生时机

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

mysql脏页是如何产生的

mysql 中,脏页是指存储在缓冲池中但尚未写入磁盘的数据页。脏页产生于事务更新、写缓冲池以及事务隔离级别、缓冲池大小、写入负载等因素。mysql 通过检查点、后台刷新及脏页刷新优先级等机制管理脏页,在写入性能和数据完整性之间取得平衡。My
mysql脏页是如何产生的
2024-06-15

mysql怎么避免死锁的产生

这篇文章主要讲解了“mysql怎么避免死锁的产生”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“mysql怎么避免死锁的产生”吧!说明1、等待事务超时,主动回滚。2、进行死锁检查,主动回滚某一
2023-06-20

MySQL - 死锁的产生及解决方案

MySQL - 死锁的产生及解决方案 1. 死锁与产生死锁的四个必要条件1.1 什么是死锁1.2 死锁产生的4个必要条件 2. 死锁案例2.1 表锁死锁2.2 行锁死锁2.3 共享锁转换为排他锁 3. 死锁排查4. 实例分析
2023-08-17

MySQL产生死锁原因分析讲解

死锁指的是在两个或两个以上不同的进程或线程中,由于存在共同资源的竞争或进程(或线程)间的通讯而导致各个线程间相互挂起等待,如果没有外力作用,最终会引发整个系统崩溃
2022-12-16

生产环境MySQL索引时效的排查过程是什么

今天小编给大家分享一下生产环境MySQL索引时效的排查过程是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。问题:mysq
2023-06-29

mysql query error产生的原因是什么

MySQL查询错误可能有多种原因,包括但不限于以下几种:1. 语法错误:查询语句的语法错误是最常见的错误之一。例如,缺少关键字、拼写错误、不正确的引号使用等等。这些错误可以通过检查查询语句的语法并进行修正来解决。2. 表或列不存在:在查询中
2023-08-31

编程热搜

目录