next-key lock案例

news2025/7/9 18:31:55

1. 加锁规则

在默认的可重复读的隔离级别下,加锁规则可以总结为:两个原则,两个优化和一个bug

  1. 原则1:加锁的基本单位是next-key lock。next-key lock是前开后闭的区间
  2. 原则2:查询过程中访问到的对象才会加锁
  3. 优化1:索引上的等值查询,给唯一索引加锁的时候,next-key lock退化为行锁
  4. 优化2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock退化为间隙锁
  5. 一个bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止。

我们创建如下的表t作为案例中的表:

CREATE TABLE T(
    id int(11) not null,
    c int(11) default null,
    d int(11) default null,
    primary key (id),
    key c(c)
)ENGINE=InnoDB;

insert into t values(0,0,0),(5,5,5),(10,10,10),(15,15.15),(20,20,20),(25,25,25);

2. 各种案例

案例一:等值查询间隙锁

在这里插入图片描述

由于表t中没有id=7的记录,所以具体加锁过程可以拆解为:

  1. 根据原则1,加锁单位是next-key lock,session A的加锁范围是(5,10]
  2. 根据优化2,因为是等值查询,并且id=10不满足条件,退化为间隙锁,所以session A 的加锁范围是(5,10)

故session B会被阻塞,而session C能够正常查询

案例二:非唯一索引等值锁

在这里插入图片描述

这个例子是关于覆盖索引的。

我们来分析加锁的过程:

  1. 根据原则1,加锁单位是next-key lock,session A的加锁范围是(0,5]
  2. 因为c是普通索引,不是唯一索引,所以访问完id=5不会马上停下来,需要继续查询,查询到id=10才会放弃。根据原则2,访问到的都要加锁,因此session A的加锁范围变成(0,10]
  3. 根据优化2,最后一个值不满足id=5,退化为间隙锁,所以session A的加锁范围是(0,10)
  4. 根据原则2,只有访问到的对象才会加锁。由于session A使用了覆盖索引,并不需要回表查询主键索引,所以只对覆盖索引加了锁(0,10)。

对于session B中的语句,使用的是主键索引,因此并没有被加锁,可以正常执行。

对于session C中的语句,要插入(7,7,7),就会被锁(0,10)锁住。

特别需要注意的是,lock in share mode只锁覆盖索引。但是for update就不一样了,因为系统会认为你接下来要更新数据,因此会顺便给主键索引上满足条件的行加上行锁

这个例子说明,锁是加在索引上的

案例三:主键索引范围锁

这个例子是关于范围查询的

我们先来看下面两条SQL语句:

mysql> select * from t where id=10 for update;
mysql> select * from t where id>=10 and id<11 for update;

虽然上面两条语句的逻辑效果是一样的,但是加锁范围却是不同的。

对于语句1,根据优化1,唯一索引上的next-key lock会退化成行锁,所以只会锁住id=10.

对于语句2,情况就会比较复杂,我们来看下面这张图:
在这里插入图片描述

我们来分析下具体的加锁过程:

  1. 开始找到id=10这一行,因为是唯一索引,所以next-key lock会退化成行锁,只会对id=10加上行锁。
  2. 接着是范围查询往后找,找到id=15这一行停下来,加上间隙锁(10,15]

因此session A的加锁范围是[10,15]。session B和sessionC就很好判断了。

需要注意的是:首次定位查到id=10是用等值查询判断的,而向右扫描则是用的范围查询。

案例四:非唯一索引范围锁

在这里插入图片描述

这个案例和上一个案例的不同之处在于使用的是非唯一索引。

我们来分析下具体的加锁过程:

  1. 首先查询到id=10,会加上next-key lock,由于不是唯一索引,所以使用不了优化1,故加上锁(5.10]。
  2. 接下来是范围查询,找到id=15,加上next-key lock,加上锁(10,15]

所以完整的加锁范围是(5,15]。session B和session C就很容易理解了。

案例五:唯一索引范围锁bug

这个案例是唯一索引范围查询中的一个bug。
在这里插入图片描述

session A是一个范围查询,按照原则1,应该是只会加入next-key lock (10,15]。并且因为id是唯一索引,所以循环判断到id=15就结束了。

但是在具体实现上,InnoDB会往前扫描到第一个不满足条件的行为止,也就是id=20.所以也会加上next-key lock (15,20]。

所以完整的加锁范围变成(10,20]。这样session B和session C都会被阻塞。

这是唯一索引在范围查询中的bug,需要额外注意

案例六:非唯一索引上存在“等值”的例子

为了更好地说明“间隙”的概念,我们给t表插入一条新的记录:

mysql> insert into t values(30,10,30);

插入了这一行之后,就有两行的c=10了。由于主键上的唯一索引,所以这两行是不一样的,它们之间也是有间隙的。如下图:
在这里插入图片描述

接下来我们来看案例:
在这里插入图片描述

这个案例虽然用的是delete语句,但是前面提到的原则和优化都是一样的。

我们来分析具体的加锁过程:

  1. 首先访问到c=10这一行,会加上next-key lock,加锁范围是(5.10]。
  2. 接着因为c是非唯一索引,所以会继续访问到c=15,加上next-key lock (10,15]。但是因为id=15不满足条件,所以会退化为间隙锁(10,15)。

所以session A的完整加锁范围是(5,15)。如下图所示:
在这里插入图片描述

然后session B和session C的情况就显而易见了。

案例七:limit语句加锁

我们再来看个案例六的对照案例:
在这里插入图片描述

这个例子中,delete语句中加入了limit 2,虽然我们知道t表里面有且仅有两条c=10的记录,所以结果上加和不加是一样的。但是加锁却不同,这是因为遍历到(c=10,id=30)这一行之后,已经满足两条结果了,就没有往后查询了。加锁范围也变成了(5,10]。如下图所示:

在这里插入图片描述

因此,session B就能正常插入了。

这个例子给我们的启示就是,删除数据的时候尽量用limit,这样可以缩小加锁的范围

案例八:死锁的例子

这个案例是为了说明next-key lock是间隙锁和行锁共同形成的。
在这里插入图片描述

我们来分析加锁的过程:

  1. 对于session A,由于c是非唯一索引,所以会查询到id=15,并且行锁退化为间隙锁。所以加锁范围是(5,10]和(10,15)。
  2. 对于session B,由于c是非唯一索引,所以会查询到id=15,并且行锁退化为间隙锁。所以正常情况下加锁范围是(5,10]和(10,15)

但是因为session B是在session A之后执行的,所以session A先对(5,10]和(10,15)进行加锁,这里包含两个间隙锁(5,10)和(10,15),以及一个行锁c=10。

接着,session B想要在(5,10]和(10,15),因为间隙锁是可以重复叠加的,所以(5,10)和(10,15)加锁成功。又因为行锁相互排斥,所以session N想要加的id=10的行锁会被session A阻塞。

再接着,session A执行insert语句,则会被session B的间隙锁阻塞。这样就形成了死锁,系统只能让session B回滚了。

这个案例的目的,就是想要告诉我们:next-key lock具体执行的时候,是要分成间隙锁和行锁两阶段执行的。而不是说因为行锁被阻塞了,也会造成间隙锁被阻塞,从而整个next-key lock被阻塞。

来源:自己整理的MySQL实战45讲笔记

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/5759.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机网络-数据交换技术

数据交换&#xff1a;实现在大规模网络核心上进行数据传输的技术基础。 常见的数据交换技术包括&#xff1a;电路交换、报文交换和分组交换。 一、电路交换 电路&#xff1a;通过中间交换结点为两台主机之间建立一条专用的通信线路。电路交换&#xff1a;是最早出现的一种交换…

这个神器,让我的 Python 代码运行速度快了100倍

Python 已经得到了全球程序员的喜爱&#xff0c;连续多期稳坐编程语言排行榜第一把交椅。但是还是遭到一些人的诟病&#xff0c;原因之一就是认为它运行缓慢。 要是有一款能够自动优化我们代码的神器该有多好啊&#xff01; 于是&#xff0c;大家都在想尽各种办法来提高 Pytho…

弘扬企业家精神!闪马智能创始人兼CEO彭垚再获殊荣

随着新业态、新活力涌现&#xff0c;诞生了一批又一批新的优秀企业家。11月8日&#xff0c;闪马智能创始人兼CEO彭垚荣膺胡润百富“2022青年产业领袖”。 自2016年起&#xff0c;彭垚连续创业&#xff0c;7年内成功培育并壮大了两家行业独角兽企业&#xff0c;2019年4月成立闪…

创龙AD+全志T3 ad_display 开发案例 (2)

上一篇&#xff1a;创龙AD全志T3 ad_display 开发案例(1) 前 言 本文主要介绍基于全志科技T3(ARM Cortex-A7)处理器的8/16通道AD采集开发案例&#xff0c;使用核芯互联CL1606/CL1616AD芯片&#xff0c;亦适用于ADI AD7606/AD7616。CL1606/CL1616与AD7606/AD7616软硬件兼容。 …

OpenCV图像处理——图像梯度

总目录 图像处理总目录←点击这里 七、图像梯度 7.1、图像梯度-Sobel算子 原图 直接计算 不建议这么算 sobelxycv2.Sobel(img,cv2.CV_64F,1,1,ksize3) sobelxy cv2.convertScaleAbs(sobelxy) cv_show(sobelxy,sobelxy)分别计算——合并 当前位置的像素值等于sobel算…

spring security调用过程;及自定义改造

认证/授权概述 一般系统都有登录接口来校验用户是否存在&#xff0c;密码是否正确&#xff0c;然后会颁发一个token给客户端&#xff0c;后续客户端就可以带着这个token来请求&#xff0c;代表自己是合法请求。 spring security责任链 请求->UsernamePasswordAuthenticati…

【MFC】打砖块小游戏(上)(5)

创建WIN32项目的时候&#xff0c;可以去掉勾选【空项目】可以减少工作量。 创建项目 文件-》新建-》 项目-》WIN32项目-》取消勾选空项目&#xff0c;完成创建 创建完成后&#xff0c;多出了很多文件&#xff0c;当然很多代码是前面已经手动写过了的&#xff1a; stdafx.h …

聚醚羰基铑功能化离子液体{[CH3O(CH2CH2O)nmim][Rhx(CO)y]}

聚醚羰基铑功能化离子液体{[CH3O(CH2CH2O)nmim][Rhx(CO)y]} 离子液体种类 目前研究较多的离子液体阳离子&#xff0c;根据有机母体的不同主要可分四种&#xff0c;即咪唑类离子[R1R3Im]、吡啶类离子[RPy]、烷基季铵类离子[NRxH4-x]以及烷基季膦类离子[PRxH4-x]。这四类阳离子…

【Designing ML Systems】第 9 章 :生产中的持续学习和测试

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

MySQL数据库的约束

文章目录一、约束是什么&#xff1f;二、约束的具体操作Not NULLUNIQUE约束的组合使用PRIMARY KEYDEFAULTFOREIGN KEY一、约束是什么&#xff1f; 约束就是&#xff0c;在创建表的时候&#xff0c;对表设置一些规则&#xff0c;只有满足这些规则&#xff0c;才可以插入数据&am…

【微服务】Nacos通知客户端服务变更以及重试机制

&#x1f496;Spring家族源码解析及微服务系列 ✨【微服务】Nacos服务发现源码分析 ✨【微服务】SpringBoot监听器机制以及在Nacos中的应用 ✨【微服务】Nacos客户端微服务注册原理流程 ✨【微服务】SpringCloud中使用Ribbon实现负载均衡的原理 ✨【微服务】SpringBoot启动流程…

字节一面后,我又看了一遍ThreadLocal核心原理

前言&#xff1a;上周在面试字节的时候&#xff0c;问到了ThreadLocal的核心原理&#xff0c;由于这个知识点当时有些淡忘&#xff0c;因此作此篇文章进行知识的记录&#xff0c;同时希望能够帮助到其他的小伙伴儿们。 本篇文章记录的基础知识&#xff0c;适合在学Java的小白&a…

动态 SQL

文章目录一、学习目的二、动态 SQL 中的元素三、条件查询操作四、更新操作五、复杂查询操作1.foreach 元素中的属性2.foreach 元素迭代数组3.foreach 元素迭代 List4.foreach 元素迭代 Map一、学习目的 在实际项目的开发中&#xff0c;开发人员在使用 JDBC 或其他持久层框架进…

【汇编 C++】多态底层---虚表、__vfptr指针

前言&#xff1a;如果对多态不太了解的话&#xff0c;可以看我的这篇文章《C多态》&#xff0c;另外本文中出现到的汇编代码&#xff0c;我都会予以解释&#xff0c;看不懂没关系&#xff0c;知道大概意思就行&#xff0c;能不讲汇编的地方我就不讲&#xff1b; 本文使用到的工…

networkx学习记录

networkx学习记录networkx学习记录1. 创建图表2. 节点3. 边4.检查图的元素5.从图中删除元素6.使用图构造函数7.访问边和邻居8.向图、节点和边添加属性9.有向图10. 绘制图形networkx学习记录 1. 创建图表 创建一个空图 import networkx as nx G nx.Graph()此时如果报以下错误…

HTML网页设计结课作业——11张精美网页 html+css+javascript+bootstarp

HTML实例网页代码, 本实例适合于初学HTML的同学。该实例里面有设置了css的样式设置&#xff0c;有div的样式格局&#xff0c;这个实例比较全面&#xff0c;有助于同学的学习,本文将介绍如何通过从头开始设计个人网站并将其转换为代码的过程来实践设计。 精彩专栏推荐&#x1f4…

学姐突然问我键盘怎么选?原来是为了这个...

前言&#xff1a; 上个星期学姐来问我该买啥键盘&#xff0c;说是自己用的笔记本的键盘实在是不太好用&#xff0c;很喜欢机械键盘的手感&#xff0c;但是常规的机械键盘有太大了而且声音十分大&#xff0c;对她们女生来说并不是很友好。于是我给她推荐了我现在正在用的这款键盘…

头歌-信息安全技术-Java生成验证码

头歌-信息安全技术-Java生成验证码一、第1关&#xff1a;使用Servlet生成验证码1、任务描述2、编程要求3、评测代码二、第2关&#xff1a;用户登录时校验验证码是否正确1、任务描述2、编程要求3、评测代码三、第3关&#xff1a;使用Kaptcha组件生成验证码1、任务描述2、编程要求…

2023年前端开发未来可期

☆ 对于很多质疑&#xff0c;很多不解&#xff0c;本文将从 △ 目前企业内前端开发职业的占比&#xff1b; △ 目前业内开发语言的受欢迎程度&#xff1b; △ 近期社区问答活跃度&#xff1b; 等维度来说明目前前端这个职业的所处位置。 ☆ 还有强硬的干货&#xff0c;通过深入…

跳槽前恶补面试题,成功上岸阿里,拿到33k的测开offer

不知不觉间&#xff0c;时间过得真快啊。作为一名程序员&#xff0c;应该都清楚每年的3、4月份和9、10月份都是跳槽的黄金季&#xff0c;各大企业在这段时间会大量招聘人才。在这段时间里&#xff0c;有人欢喜有人悲。想必各位在跳槽前都会做好充足的准备&#xff0c;同样做足了…