【MYSQL】MYSQL 的学习教程(十三)之 MySQL的加锁规则

在这里插入图片描述

1. MySQL 加锁全局视角

MySQL 分成了 Server 层和存储引擎两部分,每当执行一个查询时,Server 层负责生成执行计划,然后交给存储引擎去执行。其整个过程可以这样描述:

  1. Server 层向 Innodb 获取到扫描区间的第 1 条记录
  2. Innodb 通过 B+ 树定位到扫描区间的第 1 条记录,然后返回给 Server 层
  3. Server 层判断是否符合搜索条件,如果符合则发送给客户端,不符合,则跳过。接着继续向 Innodb 要下一条记录
  4. Innodb 继续根据 B+ 树的双向链表找到下一条记录,会执行具体的 row_search_mvcc 函数做加锁等操作,返回给 Server 层
  5. Server 层继续处理该条记录,并向 Innodb 要下一条记录
  6. 继续不停执行上述过程,直到 Innodb 读到一条不符合边界条件的记录为止

通过上面这个过程,明白两个重要的认识:

  • Innodb 并不是一次性把所有数据找到,然后返回给 Server 层的,而是会循环很多次
  • row_search_mvcc 这个函数是做具体的加锁、加什么锁的重要逻辑,并且由于 Server 层与 Innodb 会循环多次,因此该函数也是会执行多次的

弄懂了上面两个认识,会对后续大家理解有很大帮助。例如:对于 select * from user where id >= 5 进行分析的时候,为什么会出现说第一次加锁是精确查询?它明明是范围查询呀!这是因为第一次是要寻找到 id = 5 的记录,对于 Innodb 来说,它就是精确查找,不是范围查找。随后找到 id = 5 的记录之后,就要找 id > 5 的记录了,此时就变成了范围查找了

2. MySQL 加锁规则

对于 RC 隔离级别,加的排他锁(X锁),是比较好理解的,哪里更新就锁哪里。RR 隔离级别加锁有一定的规则

锁规则一共包括:两个原则、两个优化和一个 bug

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

说明:

  • 对于原则 1 说的:加锁的基本单位是 Next-Key 锁,意思是默认都是先加上 Next-Key,之后根据 2 个优化点选择性退化为行锁或间隙锁
  • 对于原则 2 说的:访问到的对象才会加锁,意思是如果直接索引覆盖到了,不需要回表,那么就不会对聚簇索引加锁。这样的话,其他事务就可以对聚簇索引进行操作,而不会阻塞

测试数据:

CREATE TABLE `t`  (`id` int NOT NULL,`c` int NULL DEFAULT NULL,`d` int NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE,INDEX `c`(`c`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
INSERT INTO `t` VALUES (0, 0, 0);
INSERT INTO `t` VALUES (5, 5, 5);
INSERT INTO `t` VALUES (10, 10, 10);
INSERT INTO `t` VALUES (15, 15, 15);
INSERT INTO `t` VALUES (20, 20, 20);
INSERT INTO `t` VALUES (25, 25, 25);

在这里插入图片描述

3. 七个案例

分7个案例去分析哈:

  1. 等值查询间隙锁
  2. 非唯一索引等值锁
  3. 主键索引范围锁
  4. 非唯一索引范围锁
  5. 唯一索引范围锁 bug
  6. 普通索引上存在"等值"的例子
  7. limit 语句减少加锁范围

3.1 案例一:等值查询间隙锁

我们同时开启 A、B、C三个会话事务,如下:

在这里插入图片描述

发现事务 B 会阻塞等待,而 C 可以执行成功

分析流程:

  1. 在事务 A 中,要查找 id = 7 的记录,其查找过程为:从左到右查找 id 聚簇索引,依次对比 0、5 两个索引,发现不对。接着,对比 10 这个索引,发现 7 <10,于是停止搜索。根据原则 1,默认给其加上一个 Next-Key 锁,即 (5, 10]
  2. 同时根据优化 2,这是一个等值查询 (id=6),而 id=10 不满足查询条件。所以 next-key lock 退化成间隙 Gap 锁,因此最终加锁的范围是 (5,10)

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

按顺序执行事务会话A、B、C,如下:

在这里插入图片描述

发现事务B可以执行成功,而 C 阻塞等待

分析流程:

  1. 在事务 A 中,要查找 c=5 的记录,其中 c 是非唯一索引。其查找过程为:从左到右查找 c 索引,找到了 c=5 的索引,根据原则 1,对其加 Next-Key 锁,即 (0,5]
  2. 由于普通索引可能重复,因此其还会继续往后搜索,接着搜索到 10,根据原则 2,访问到的都要加锁,因此再给其加 Next-Key 锁,即 (5,10]
  3. 根据优化2:等值判断,向右遍历,最后一个值 10 不满足 c = 5 这个等值条件,因此退化成间隙锁 (5,10)
  4. 根据原则 2 :只有访问到的对象才会加锁,事务 A 的这个查询使用了覆盖索引,没有回表,并不需要访问主键索引,因此主键索引上没有加任何锁,事务会话 B 是对主键 id 的更新,因此事务会话 B 的 update 语句不会阻塞

3.3 案例三:主键索引范围锁

按顺序执行事务会话A、B、C,如下:

在这里插入图片描述

事务 B:插入 id = 12 时阻塞;插入 id = 6 时顺利执行;
事务 C:阻塞

分析流程:

  1. 事务 A 开始执行的时候,要找到 id 为 10 的记录,于是从左到右找到了 id 为 10 的索引。根据原则 1 会给其加 Next-Key 锁,即 (5,10]
  2. 又因为 id 是主键,也就是唯一值,因此根据优化1:索引上的等值查询,给唯一索引加锁时,next-key lock 退化为行锁(Record lock)。所以只加了 id=10 这个行锁
  3. 接着继续进行范围查找,找到 id=15 这一行,继续加 Next-Key 锁 (10,15]。这时候 id=15 大于 11,因此其不再查找

事务会话 A 执行完后,加的锁是 id=10 这个行锁,以及临键锁 next-key lock(10,15]

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

按顺序执行事务会话 A、B、C,如下:

在这里插入图片描述

发现事务会话 B 和事务会话 C 的执行 SQL 都被阻塞了

分析流程:

  1. 事务 A 开始执行的时候,要找到 id 为 10 的记录,根据原则 1 加了 Next-Key 锁,即 (5,10]。 由于索引 C 是非唯一索引,不符合优化1,因此不会退化为行锁
  2. 接着继续进行范围查找,找到 id=15 这一行停下来,因此还需要加 next-key lock (10,15]

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

按顺序执行事务会话 A、B、C,如下:

在这里插入图片描述

事务 B 阻塞;事务 C 阻塞

分析流程:

  1. 事务 A 开始执行的时候, 0、5、10 都不满足条件,找到 id = 15 的行满足,根据原则1,会加上next-key lock(10,15]
  2. 因为 id 是主键,即唯一的,因此循环判断到 id = 15 这一行就应该停止了
  3. 根据一个 bug:InnoDB 会往前扫描到第一个不满足条件的行为止,直到扫描到 id = 20。而且由于这是个范围扫描,因此索引 id 上的 (15,20] 这个 next-key lock 也会被锁上

3.6 案例六:普通索引上存在"等值"的例子

插入一条数据:

insert into t values(28,10,66);

则 c 索引树如下:

在这里插入图片描述

c 索引值有相等的,但是它们对应的主键是有间隙的。比如(c=10,id=10)和(c=10,id=28)之间

按顺序执行事务会话A、B、C,如下:

在这里插入图片描述

事务 B 阻塞;事务 C 顺利执行

分析流程:

  1. 事务 A 开始执行的时候,要找到 c 为 10 的记录,根据原则 1,加一个(c=5,id=5) 到 (c=10,id=10)的 next-key lock(5, 10]
  2. 由于 c 是非唯一索引,会继续向右进行范围查找,直到碰到 (c=15, id=15) 这一行,循环才结束,会加一个 next-key lock(10, 15]。根据优化 2,这是一个等值查询,向右查找到了不满足条件的行,所以会退化成间隙锁 (10, 15)

在索引 c 上的加锁范围,就是下图灰色阴影部分的:

在这里插入图片描述

3.7 案例七:limit 语句减少加锁范围

事务A、B执行如下:

在这里插入图片描述

事务 B 顺利执行

分析流程:

  1. 事务 A 开始执行的时候,要找到 c 为 10 的记录,根据原则 1,加一个(c=5,id=5) 到 (c=10,id=10)的 next-key lock(5, 10]
  2. 因为明确加了limit 2的限制后,因此在遍历到 (c=10, id=30) 这一行之后,满足条件的语句已经有两条,循环就结束了

如下图所示:

在这里插入图片描述

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

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

相关文章

从网页连接socket服务器和I/O

1.i/o InputStream和InputStreamReader是Java I/O类库中的两个关键类&#xff0c;用于处理字节流。它们的主要区别在于它们处理数据的方式。 InputStream: InputStream是用于读取字节流的抽象类。它是所有字节输入流类的父类。InputStream的子类可以从不同的数据源读取字节&…

rime中州韵小狼毫 随机数 随机码 电脑信息 滤镜

在输入法中支持生成GUID&#xff0c;或者随机数&#xff0c;随机字符&#xff0c;获取自身电脑信息&#xff0c;这将是一个非常酷的功能。 先睹为快 本文所分享滤镜&#xff0c;主要用于生成一些动态的信息词条&#xff0c;效果如下&#x1f447;&#xff1a; GUID.lua GU…

如何正确地理解应用架构并开发

许多同学或多或少都经历过这样的流程&#xff1a; 新同学刚来公司&#xff0c;学习了解团队的一些工程代码&#xff0c;并了解其中的代码风格团队新接手了一些其他团队的项目&#xff0c;需要了解工程结构以及概念如何定义工程项目的工程结构&#xff0c;包目录结构并达成团队共…

抖音矩阵云混剪系统源码 短视频矩阵营销系统V2.2.1(免授权版)

抖音矩阵云混剪系统源码 短视频矩阵营销系统V2.2.1&#xff08;免授权版&#xff09; 中网智达矩阵营销系统多平台多账号一站式管理&#xff0c;一键发布作品。智能标题&#xff0c;关键词优化&#xff0c;排名查询&#xff0c;混剪生成原创视频&#xff0c;账号分组&#xff…

Redis主从复制、哨兵及集群

目录 简介 主从复制 哨兵 集群 1.Redis 主从复制 主从复制的作用 主从工作原理 主从复制搭建 安装redis 修改redis配置文件Master节点操作 修改 Redis 配置文件slave节点操作 验证主从效果 2.Redis 哨兵模式 哨兵模式的作用 哨兵结构组成部分 故障转移机制 主…

API(Math类,System类,Runtime类,Object类,Objects类,BigInteger类,BigDecimal类)

文章目录 课程目标1 Math类1.1 概述1.2 常见方法1.3 算法小题(质数)1.4 算法小题(自幂数)1.5 课后练习 2 System类2.1 概述2.2 常见方法 3 Runtime3.1 概述3.2 常见方法3.3 恶搞好基友 4 Object类4.1 概述4.2 常见方法 5 Objects类5.1 概述5.2 常见方法 6 BigInteger类6.1 引入…

vue-vben-admin 与.net core 结合实例 【自学与教学 小白教程】---第4节---部门管理

ue-vben-admin 与.net core 结合实例 这里计划使用.net core 作为后端 。目标&#xff1a;打造好看 易用 开箱即用 的netcore一体化框架。Vue Vben Admin For NetCore 取命 hcrain-vvadmin 我不是前端人员 但有时开发还是要写一些界面。 之前使用layui是时候 狠心升级下了。 …

【教3妹学编程-算法题】移除后集合的最多元素数

3妹&#xff1a;好冷啊&#xff0c; 冻得瑟瑟发抖啦 2哥 : 这才哪跟哪&#xff0c;上海这几天温度算是高的啦。你看看哈尔滨&#xff0c;那才是冰城。 3妹&#xff1a;据说沈阳千名“搓澡大姨”支援哈尔滨&#xff1f;哈哈哈哈 2哥 : 就像今年的淄博烧烤&#xff0c;可能有炒作…

LabVIEW在微生物检测中的应用

随着对食品安全关注的增加&#xff0c;食品检测的准确性变得越来越重要。其中&#xff0c;微生物计数作为食品合格的关键指标&#xff0c;对其检测技术的准确性和实时性要求极高。传统的微生物检测面临着菌落识别困难、设备实时性差和自动化程度不高等问题&#xff0c;尤其在疫…

GB28181视频汇聚平台EasyCVR级联后,部分通道视频无法播放是什么原因?

GB28181协议智慧安防平台EasyCVR是基于各种IP流媒体协议传输的视频汇聚和融合管理平台。视频流媒体服务器EasyCVR采用了开放式的网络结构&#xff0c;支持高清视频的接入和传输、分发&#xff0c;平台提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制…

Hystrix

Hystrix简介 Hystrix是由Netflix开源的一个延迟和容错库&#xff0c;用于隔离访问远程系统、服务或者第三方库&#xff0c;防止级联失败&#xff0c;从而提升系统的可用性与容错性。 断路器本身是一种开关装置,当某个服务单元发生故障后,通过断路器的故障监控(类似熔断保险丝…

图解Kubernetes的服务(Service)

pod 准备&#xff1a; 不要直接使用和管理Pods&#xff1a; 当使用ReplicaSet水平扩展scale时&#xff0c;Pods可能被terminated当使用Deployment时&#xff0c;去更新Docker Image Version&#xff0c;旧Pods会被terminated&#xff0c;然后创建新Pods 0 啥是服务&#xf…

[工具探索]-PS处理图片文字

以下涉及到用PS进行图片中文字的删减、替换、修改等操作&#xff0c;比较琐碎&#xff0c;不过用替换方式可以做到无印记 1、将图片中中局部删除 &#xff08;1&#xff09;导入图片信息&#xff08;2&#xff09;首先双击图层解锁&#xff0c;然后按住alt键拖动图层&#xf…

Open CASCADE学习|创建拓朴

目录 1、创建点gp_Pnt 2、创建向量gp_Vec 3、创建边TopoDS_Edge 4、线网络TopoDS_Wire 5、面TopoDS_Face 6、体TopoDS_Shape OpenCascade中的拓朴实体如下图所示&#xff0c;其中Compound可以包含很多Solid&#xff1b;Solid由Shell包围而成&#xff1b;Shell由相连的Fac…

LeetCode 36 有效的数独

题目描述 有效的数独 请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 &#xff0c;验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。&#xff08;请参考…

MySQL连续案例续集

01&#xff09;查询学过「张三」老师授课的同学的信息 SELECT s.*, c.cname, t.tname, sc.score FROM t_mysql_teacher t, t_mysql_course c, t_mysql_student s, t_mysql_score sc WHERE t.tid c.tid AND c.cid sc.cid AND sc.sid s.sid AND t.tname ‘张三’ 02&#x…

uniapp微信小程序投票系统实战 (SpringBoot2+vue3.2+element plus ) -创建图文投票实现

锋哥原创的uniapp微信小程序投票系统实战&#xff1a; uniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )_哔哩哔哩_bilibiliuniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )共计21条视频…

【SQL】对表中的记录通过时间维度分组,统计出每组的记录条数

场景&#xff1a;一般用作数据统计&#xff0c;比如统计一个淘宝用户在年、月、日的维度上的订单数。 业务&#xff1a;一个集合&#xff0c;以时间维度来进行分组求和。 准备一张订单表order&#xff0c;有一些常规属性&#xff0c;比如创建时间&#xff0c;订单号。 DDL语句如…

【2023】java常用HTTP客户端对比以及使用(HttpClient/OkHttp/WebClient)

&#x1f4bb;目录 1、介绍2、使用2.1、添加配置2.1.1、依赖2.1.2、工具类2.1.3、实体2.1.4、Controller接口 2.2、Apache HttpClient使用2.3 、OkHttp使用2.4、WebClient使用 1、介绍 现在java使用的http客户端主要包括以下几种 而这些中使用得最频繁的主要是&#xff1a; A…

Deno 1.22 发布

目录 更新默认的类型检查模式 移除Deno.emit()Deno.formatDiagnostics()和Deno.applySourceMap() API 默认启用Deno命名空间 --no-config标识 Navigator.userAgent 更新 Deno.resolveDns() API 引入新的Response.json()静态方法 在 LSP 默认启用 Linting 对测试运行程…