我打赌!这个 SQL 题,大部分人答不出来

news2024/11/26 16:41:36

周末的时候,一个读者问了我一个很有意思的问题,是关于 MySQL 中 update 加锁的问题。

他用下面这张数据库表,做了个 MySQL 实验的时候。

图片

发现事务 B 的 update 不会阻塞,而事务 C 的 update 会阻塞,都是对 id = 10 这条记录进行 update, 为什么一个会阻塞,一个不会阻塞?

图片

首先,我们先来分析下,事务 A 这条 SQL 加了什么锁。

// 事务 A 
select * from t_person where id < 10 for update;

我直接说结论,事务 A  加了这三个行级锁:

  • 在 id 为 1 的主键索引上,加了 X 型的 next-key 锁,范围是 (-∞,1]。意味着,其他事务无法对 id = 1 的记录进行删除和更新操作,同时无法插入 id 小于 1 的新记录。

  • 在 id 为 5 的主键索引上,加了 X 型的 next-key 锁,范围是 (1, 5]。意味着,其他事务无法对 id = 5 的记录进行删除和更新操作,同时无法插入 id 为 2、3、4 的新记录。

  • 在 id 为 10 的主键索引上,加了 X 型的间隙锁,范围是 (5, 10)。意味着,其他事务无法插入 id 为 6、7、8、9 的新纪录。

事务 B 的 update 语句为什么不会阻塞?

事务 B 的 update 语句是对 id = 10 的行记录的 name 字段进行更新。

// 事务 B
update t_person set name = "小林" where id = 10;

事务 B 会在 id = 10 的主键索引上加 X 型记录锁,仅锁住这一行。因为当我们用唯一索引进行等值查询的时候,查询的记录是「存在」的,在索引树上定位到这一条记录后,该记录的索引中的 next-key 锁会退化成「记录锁」

事务 A 并没有对 id = 10 的主键索引上加 X 型记录锁,而是对 id = 10 的主键索引上加 X 型间隙锁。间隙锁和记录锁之间是没有互斥关系的,所以事务 B 的 update 语句不会阻塞

事务 C 的 update 语句为什么会阻塞?

事务 C 的 update 语句是将 id = 10 的行记录的 id 更新为 2。

// 事务 C
update t_person set id = 2 where id = 10;

这条 update 很特殊,特殊之处在于更新了主键索引。你以为它只是一个更新操作,实际上它在背后执行了两个操作

  • 操作 1:delete from t_person where id = 10;

  • 操作 2:insert into t_person (2, 陈某,  30, 广州市海珠区);

也就是先删除 id = 10 的记录,然后再插入 id = 2 的新纪录。

为什么当 update 语句更新了索引值,会被拆分成删除和插入操作?

要回答这个问题,我们先要清楚 B+ 树的特点。

Innodb(MySQL 存储引擎)在实现索引的时候,采用的数据结构是 B+ 树。B+ 树是基于二分查找树演变过来的,所以 B+ 树在存储索引的时候,是按顺序存储的,因为这样才能利用二分查找快速检索到索引。

现在有一颗这样的  B+ 树,可以看到叶子节点的索引值是从小到大的顺序。

图片

假设这时候需要将索引值为 25 更新为 3,如果直接索引值为 25 的位置上,将值改为 3 的话。

图片

这时候你就会发现这棵 B+ 树不满足顺序性了!

所以更新索引的值,不能只是修改一个索引值就完事,而是还要保证更新后的索引值能继续满足  B+ 树的顺序性。

解决的方法就是,先删除索引值为 25 的节点,再插入索引值为 3 的节点,这样,这颗 B+ 树才能满足顺序性。

图片

事务 C 的 update  语句具体阻塞在哪个「操作」?

现在我们知道,事务 C 的 update 特殊语句背后执行了两个操作,分别是删除和插入操作,那具体是阻塞在哪个「操作 」?

「操作 1 」是删除 id = 10 的记录,事务 C 是会在 id = 10 的主键索引上加 X 型记录锁,而事务 A 并没有对 id = 10 的主键索引上加 X 型记录锁,而是对 id = 10 的主键索引上加 X 型间隙锁。间隙锁和记录锁之间是没有互斥关系的,所以「操作 1 」不会阻塞

根据排除法,既然 「操作 1 」不会阻塞,那事务 C 的 update 语句阻塞的原因就是因为 「操作 2」发生了阻塞。

为什么「操作2」会发生阻塞呢?

我们先要知道,插入操作什么时候会发生阻塞:插入语句在插入一条新记录之前,需要先定位到该记录在 B+树的位置,如果插入的位置的下一条记录的索引上有间隙锁,此时会生成一个插入意向锁,然后锁的状态设置为等待状态,现象就是插入语句会被阻塞。

「操作 2」插入的是 id = 2 的新记录,在主键索引的 B+树定位到插入的位置如下图。

图片

插入位置的下一条记录是 id = 5 的记录,而事务 A 在 id 为 5 的主键索引上已经加了 X 型的 next-key 锁,这里面包含了间隙锁。所以「操作 2」的插入操作会发生阻塞,这就是事务 C 的 update 语句阻塞的原因。

从这我们也可以知道间隙锁的作用,就是阻止其他事务在间隙锁的范围内插入新记录,从而避免可重复读隔离级别下幻读的现象。

我们也可以通过 select * from performance_schema.data_locks\G; 这条语句,查看事务 C 在加什么锁的时候导致阻塞。

图片

从上面的输出信息,可以看到事务 C 在加「插入意向锁」的时候,发生了阻塞。

插入意向锁是插入操作才会有的锁,而事务 C 只是执行 update 语句,却出现了插入意向锁,从这里也可以证明,事务 C 这条特殊的 update 语句运行的时候,被拆分成了两个操作,一个是删除,另一个是插入。

总之,如果 update 语句更新的是普通字段的值,就会对发生更新的记录加 X 型记录锁。

但是,如果 update 语句更新的是索引的值,那么在运行的时候会被拆分成删除和插入操作,这时候分析锁的时候,要从这两个操作的角度去分析

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

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

相关文章

使用 uniswap 模拟交易时遇到一个问题

使用 uniswap 模拟交易时遇到一个问题 Error: VM Exception while processing transaction: socket hang upat web3.js:6365:9(39)at send (web3.js:5099:62(29))at <eval>:1:20(11)我的入参是 > eth.sendTransaction({from:0xe26a357fcc5A010421A49B8a5A99Af14CDe2…

Elasticsearch 中的矢量搜索:设计背后的基本原理

作者&#xff1a;Adrien Grand 你是否有兴趣了解 Elasticsearch 用于矢量搜索&#xff08;vector search&#xff09;的特性以及设计是什么样子&#xff1f; 一如既往&#xff0c;设计决策有利有弊。 本博客旨在详细介绍我们如何选择在 Elasticsearch 中构建矢量搜索。 矢量搜索…

科研 | 入门大全

文章目录 1. 读文献1.1 文献查阅与管理、如何快速找到与研究方向相关文章如何快速了解国内外发展现状找到后&#xff0c;怎么高效阅读&#xff1f;需要逐词逐句阅读吗&#xff1f;需要顺序阅读&#xff1f;读完之后&#xff0c;好像懂了&#xff0c;好像也没懂读过的文章&#…

通过GWO算法对8个发电机进行了最佳调度编码(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 通过GWO&#xff08;Grey Wolf Optimization&#xff09;算法对8个发电机进行最佳调度编码是一种优化问题的解决方法。GWO算法灵…

【C++】C++异常机制

文章目录 C异常C语言传统的错误处理方式C错误处理方式异常的使用方法异常的使用规范异常安全问题异常规范自定义异常体系STL中的异常体系异常的优缺点 C异常 C语言传统的错误处理方式 终止程序&#xff0c;如assert直接断言报错&#xff0c;缺陷&#xff1a;非常麻烦&#xff…

密码学总结杂七杂八的wp

快捷键 折叠&#xff08;展开&#xff09;所有代码这里是指按下快捷键后凡事.py文件里可折叠的都折叠。 折叠所有代码&#xff1a;Ctrl Shift - &#xff08;减号&#xff09; 展开所有代码&#xff1a;Ctrl Shift &#xff08;加号&#xff09; 折叠&#xff08;展开&…

Linux运维面试题(一)之网络基础类面试题

Linux运维面试题&#xff08;一&#xff09;之网络基础类面试题 1.简述ISO/OSI的七层模型的分层与作用2.TCP/IP 四层&#xff08;网络接口层&#xff09;/五层模型&#xff08;数据链路层物理层&#xff09;3.TCP协议与UDP协议工作在哪一层&#xff0c;作用是什么&#xff1f;4…

Java安全——JAAS

Java安全 从保护终端用户不受攻击的角度讨论&#xff1a; 默认沙箱可以保护终端用户不受恶意java程序的破坏数字签名可以保护终端用户数据的完整性加密则可以保护终端用户数据的机密性 如何防止终端用户的破坏的&#xff1f; 鉴别与授权&#xff08;Java Authentication and Au…

渗透专题丨Vulnhub-DC-1靶机打靶

打开靶机&#xff0c;使用nmap进行网段扫描&#xff1a; 排除主机和kali IP&#xff0c;锁定靶机IP&#xff1a;192.168.38.141&#xff1a; 接下来进行端口扫描&#xff1a; 扫描服务详细信息&#xff1a; 这里扫到内容管理系统&#xff0c;网站也扫出来了&#xff1a;http-ge…

每天高频算法题-DAY3

题目一 在一个 n * m 的二维数组中&#xff0c;每一行都按照从左到右 非递减 的顺序排序&#xff0c;每一列都按照从上到下 非递减 的顺序排序。请完成一个高效的函数&#xff0c;输入这样的一个二维数组和一个整数&#xff0c;判断数组中是否含有该整数。 示例: 现有矩阵 ma…

电路分析 day01 一种使能控制电路

本次分析的电路为 一种使能控制电路 &#xff08;站在别人的肩膀上学习&#xff09; 资料来源 &#xff1a; 洛阳隆盛科技有限责任公司的专利 申请号&#xff1a;CN202022418360.7 1.首先查看资料了解本次电路 1.1 电路名称&#xff1a; 一种使能控制电路 1.2 电路功能…

Can转RTU网关can总线转以太网设备

YC-CAN-RTU 是一款用于 CAN-Modbus 现场总线与 RS-232 总线或 RS-485 总线之间数据转换的协议型转换器&#xff0c;支持标准 Modbus RTU 协议。集成 1 路RS-232 通道、1 路RS-485 通道、1 路CAN-Modbus 通道&#xff0c;可以方便地嵌入使用 RS-232 接口和 RS-485 接口的节点上&…

通过层级列表循环生成树结构

列表生成树结构 应用 前提: 列表有字段能表示所处层级(如Deep、Level).根据自己业务来。主要是针对列表对象来处理&#xff0c;组织成树结构。如下图&#xff1a; 在得到如图类似数据后&#xff0c;采取使用函数来组织树结构&#xff0c;同时生成层级序号&#xff08;1&…

TCP 与UDP区别

目录 网络参考模型TCPTCP 是什么特点 UDPUDP 是什么特点 TUP与UDP区别 总结什么时候选TCP or UDP 网络参考模型 TCP TCP 是什么 传输控制协议&#xff08;TCP&#xff09;是TCP/IP模型的传输层协议。它是一个面向连接的协议。因此&#xff0c;协议首先在源和目标之间建立连接…

《面试1v1》Redis内存优化

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…

WEB阶段_HTML(附代码笔记)

&#xff08;一&#xff09;案例一&#xff1a;网站信息页面的显示 1、HTML文档的创建 <html><head><title>01-HTML的文件创建&#xff08;浏览器标签显示的名字&#xff09;</title></head><body><h2>你好</h2></body>…

点云3D检测算法-Point pillar踩坑日记

工程地址&#xff1a; https://github.com/nutonomy/second.pytorch 1.环境搭建&#xff0c;跟着官网的教程走 1.1注意官网上的这条语句&#xff0c;存在一些坑 conda install pytorch torchvision -c pytorch 它会重新安装cudatoolkit和cudnn&#xff0c;版本可能很老旧&…

libtorch 调用模型方法

libtorch 是 pytorch 的 C 版本&#xff0c;支持 CPU 端和 GPU 端的模型部署。相较于用 tensorrt 部署 pytorch 模型&#xff0c;用 libtorch的优势在于&#xff1a;pytorch 和 libtorch 同属一个生态&#xff0c;API 语句比较接近&#xff0c;并且不会出现某网络层不支持的问题…

面试官:请求转发和请求重定向有什么区别?

在 Java 中&#xff0c;跳转的实现方式有两种&#xff1a;请求转发和请求重定向&#xff0c;但二者是完全不同的&#xff0c;所以我们今天就来盘它。请求转发和请求重定向主要区别&#xff0c;包含以下 5 点&#xff1a; 定义不同 跳转方不同 数据共享不同 最终 URL 地址不同…

路径规划算法:基于侏儒猫鼬优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于侏儒猫鼬优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于侏儒猫鼬优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化…