一篇文章让你秒懂MySQL中的各种锁

news2024/9/27 21:52:12

目录

  • 一、序言
  • 二、各种锁详细介绍
    • 1、Shared and Exclusive Locks(共享锁和读占锁)
    • 2、Intention Locks(意向锁)
    • 3、Record Locks(记录锁)
    • 4、Gap Locks(间隙锁)
    • 5、Next Key Locks (Next Key锁)
    • 6、Insert Intention Locks (插入意向锁)
    • 7、AUTO-INC Locks (自增锁)
    • 8、Predicate Locks for Spatial Indexes (空间索引Predicate锁)
  • 三、Server层的MDL(Metadata Lock)锁
  • 四、总结

一、序言

在MySQL中大部分存储引擎用的都是InnoDB,因此我们具体聊聊InnoDB中支持的锁类型,本章节中的内容会根据mysql 8.0版本官方文档翻译进行阐述。

InnoDB中锁的主要类型,如下:

  • Shared and Exclusive Locks:共享锁和独占锁。
  • Intention Locks:意向锁。
  • Record Locks:记录锁。
  • Gap Locks:间隙锁。
  • Next-Key Locks:Next-Key锁。
  • Insert Intention Locks:插入意向锁。
  • AUTO-INC Locks:自增锁。
  • Predicate Locks for Spatial Indexes:用于空间索引的Predicate锁。

二、各种锁详细介绍

1、Shared and Exclusive Locks(共享锁和读占锁)

InnoDB实现了标准级别的锁,这种锁主要有两种类型,共享锁(S)独占锁(X)

  • 共享锁(S)允许获得锁的事务读行数据。
  • 独占锁(X)允许获得锁的事务去更新或者删除行。

如果事务T1已经获取了某行数据R的共享锁,然后事务T2针对这行数据R获取锁的请求将如下处理:

  • 事务T2如果请求获取共享锁(S),那么将会授权成功。T1和T2两个事务都会持有对数据行R的共享锁(S)。
  • 事务T2如果请求获取独占锁(X),那么授权将会失败,事务T2必须等待T1释放共享锁(S)

备注:共享锁和读占锁只是一种概念,表级别和行级别都有共享锁和独占锁。

2、Intention Locks(意向锁)

InnoDB支持多粒度锁,可以让表锁和行锁共存,这种机制通过意向锁来实现,所谓的意向锁其实是表级别的锁,用来指定事务对某数据行加共享锁或独占锁。意向锁主要有两种类型:

  • 意向共享锁(IS):事务倾向于对表中的行加共享锁,在事务对表中的某行获取共享锁之前,必须获取IS锁。
  • 意向独占锁(IX):事务倾向于对表中的行加独占锁,在事务对表中的某行获取独占锁之前,必须获取IX锁。

意向加锁示例如下:

加IS锁SELECT ... FOR SHARE
加IX锁SELECT ... FOR UPDATE

表级别锁类型兼容性总结如下表:
在这里插入图片描述
意向锁设计的主要目的是为了表明事务正在锁定某行或者将要锁定某行。

3、Record Locks(记录锁)

所谓记录锁是针对唯一索引记录的锁,如果c1是唯一索引列,执行SQL:SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE。其它事务不能对c1等于10的记录进行修改、删除、新增。

记录锁总是会锁定索引记录,即使表本身没有索引,InnoDB也会创建隐藏的聚簇索引用于记录的锁定。

4、Gap Locks(间隙锁)

间隙锁用来锁定索引记录之间的间隙,第一条索引记录前或者最后一条索引记录的后面。间隙可以跨越单个索引值、多个索引值,甚至是空值。

这句话可能不好理解,举个例子,表t01上有idvalue两列,id为主键,value为索引列。

create table t01
(
    id    bigint primary key auto_increment comment '主键',
    value bigint not null comment '值'
) comment '测试表t01';

create index idx_t01_value on t01 (value);

insert into lock_test.t01 (id, value)
values  (1, 1),
        (2, 2),
        (10, 5),
        (11, 9),
        (15, 10),
        (25, 25);

事务T1执行如下SQL:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t01 where value between 5 and 10 for update;
+----+-------+
| id | value |
+----+-------+
| 10 |     5 |
| 11 |     9 |
| 15 |    10 |
+----+-------+
3 rows in set (4.30 sec)

上面的语句针对value列会产生 (2 , 5), (5 , 10), (10, 25) 3个间隙,也就是说value在[2 , 25)之间的插入都会失效。

t01表中数据如下:
在这里插入图片描述

事务T2执行如下SQL:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t01(id, value) values (26,5);
^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted

mysql> insert into t01(id, value) values (26,2);
^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted

mysql> insert into t01(id, value) values (15,1);
^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted

间隙锁其实是性能和并发度之间权衡,它只针对隔离级别为可重复读才生效,其它隔离级别是不会生效的。

间隙锁锁定行记录锁时并不是根据唯一索引去搜寻记录,如果表中的某列为唯一索引,那么此时不会上间歇锁,而是使用上面提到的记录锁。

假设id为主键或者唯一索引,那么下面这条SQL只会锁定id为100的记录。

SELECT * FROM child WHERE id = 100;

5、Next Key Locks (Next Key锁)

所谓的Next Key锁其实就是记录锁和间隙锁(只锁定索引记录前)的结合,InnoDB在对数据行加锁时会扫描表中的索引,并且对索引记录加共享锁或者独占锁。

咱们还是拿t01表中的数据举例:
在这里插入图片描述

事务T1执行如下SQL:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t01 where value = 9 for update ;
+----+-------+
| id | value |
+----+-------+
| 11 |     9 |
+----+-------+
1 row in set (0.00 sec)

上面的语句将会产生行记录锁,锁定value为9的记录,还会产生间隙锁,锁定间隙[5 , 9)之间的记录(即上面说的索引记录9之前的一个间隙),也就是说插入value为[5, 9]的记录都会失败。

事务T2执行如下SQL:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t01(id, value) values (26,8);
^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t01(id, value) values (3,25);
^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted

mysql> insert into t01(id, value) values (26,5);
^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted

两个的组合也就是所谓的Next Key锁,这里的间隙锁只锁定了value为5到9之间的记录,因为查询条件是等值查询

不同查询条件对间隙锁的锁定范围也会有影响,依然用上面t0表的数据为例:

  • between 5 and 10之类的范围查询会让间隙锁范围更大,不止锁定索引记录前,而且会锁定索引记录后的记录,产生了 (2 , 5), (5 , 10), (10, 25) 3个间隙。
  • where value > 5 and value < 10的范围查询只会产生 (5, 10) 这个间隙。

6、Insert Intention Locks (插入意向锁)

插入意向锁其实是由INSERT操作在行插入之前设置的一种间隙锁,当多个事务插入记录到相同索引间隙时彼此并不需要互相等待,除非插入到间隙里相同的位置。

这句话似乎晦涩难懂,咱们还是用t01表中的数据举例:
在这里插入图片描述

事务T1执行如下SQL:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t01 where value > 10 for update;
+----+-------+
| id | value |
+----+-------+
| 25 |    25 |
+----+-------+
1 row in set (0.00 sec)
mysql> rollback;

上面这条语句会对value 大于10的记录加上间隙锁。

事务T2执行如下SQL:

mysql> begin;
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t01(id, value) values (26,11);
Query OK, 1 row affected (21.57 sec)

事务T3执行如下SQL:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t01(id, value) values (27,12);
Query OK, 1 row affected (6.00 sec)

当事务T1未结束之前,事务T2和T3的插入操作都会等待,当事务T1结束之后,事务T2和事务T3虽然插入的value值都在间隙锁定的范围内,但都会执行成功,T2和T3之间不需要互相等待。这就是所谓的插入意向锁的概念。

但如果事务T2和T3插入的是同一个位置,比如T2也执行如下SQL,那么事务T2会挂起。

insert into t01(id, value) values (26,11);

7、AUTO-INC Locks (自增锁)

自增锁是一种特殊的表级别的锁,当事务插入数据到自增列时就会触发。当某个事务在往表中插入数据时,另外一个事务必须等待上个事务执行完毕,实现主键的连续自增。

8、Predicate Locks for Spatial Indexes (空间索引Predicate锁)

InnoDB本身支持空间索引(为数据类型为空间类型的列设置的索引),涉及到空间索引相关的锁操作,使用Next-Key锁无法支持可重复读序列化这两个隔离级别,因为对于多维的数据是没有绝对排序的概念。

为了对有空间索引的表也支持上述的可重复读和序列化隔离级别,InnoDB会用Predicate锁来进行处理。

备注:关于空间索引和空间数据类型大家可以去官方文档上看详细描述,这里不再赘述。


三、Server层的MDL(Metadata Lock)锁

上面概述的锁都是基于存储引擎InnoDB的,在MySQL Server层也有锁,我们称为MDL(Metadata Lock)锁。

元数据锁不依赖任何存储引擎。此锁不需要显示调用,只要有事务在执行,对应的连接就会取得元数据。当事务执行的时候理论上是不能容忍表结构在中途发生改变。

  • MDL锁分为读锁和写锁。读锁和写锁互斥;
  • Select和DML语句申请读锁。MDL读锁之间不冲突,所以多个Select和DML语句可以同时执行。
  • DDL语句申请写锁,获取写锁时需要等待读锁释放,且申请写锁后会阻塞后续所有MDL锁的获取。

备注:update语句是读锁,因为它修改的是表的数据,而不是结构。

举个例子,事务T1开始执行如下SQL:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t01;
+----+-------+
| id | value |
+----+-------+
|  1 |     2 |
|  2 |     3 |
|  7 |     8 |
+----+-------+
3 rows in set (0.00 sec)

事务T2开始执行如下SQL:

mysql> drop table t01;
^C^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted

mysql> alter table t01 add index `index_value` (`value` ASC);
^C^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted

结论:当开启事务时,事务T1中select语句会获取MDL读锁,而T2中的drop和alter等DDL语句会申请MDL写锁,由于读写锁互斥,所以T2中的DDL操作都会失败。


四、总结

上述我们对锁的类型做了一个详细的阐述,无论是基于存储引擎的还是基于Server的,这里我们再归类一下:

  • 根据功能划分:分为共享锁(S)独占锁(X),S锁和X锁互斥。
  • 根据粒度划分:分为表级锁行级锁,表级锁有意向锁(Intention Lock)自增锁(AUTO-Inc)。行级锁有记录锁(Record Locks)间隙锁(Gap Locks)Next-Key锁插入意向锁(Insert Intention Locks)
  • 根据实现划分:分为Server层实现的元数据锁(Metadata Lock)存储引擎实现的锁。
    在这里插入图片描述

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

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

相关文章

java 生成.h文件,java调用c语言dll动态链接库流程

** 1、首先创建一个java文件&#xff0c;里面最好不要有中文 ** /*** BelongsPackage: PACKAGE_NAME* Author: wangqian* CreateTime: 2024-09-27 18:42:24* Describe:*/ public class testDll {static {System.loadLibrary("testDll");}public native int add(…

思科安全网络解决方案

《网安面试指南》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484339&idx1&sn356300f169de74e7a778b04bfbbbd0ab&chksmc0e47aeff793f3f9a5f7abcfa57695e8944e52bca2de2c7a3eb1aecb3c1e6b9cb6abe509d51f&scene21#wechat_redirect 《Java代码审…

NVLM多模态 LLM 在图像和语言任务中的表现优于 GPT-4o

论文地址&#xff1a;https://arxiv.org/pdf/2409.11402 背景 传统的多模态 LLM 有两种主要方法&#xff1a;纯解码器架构&#xff08;如 LLaVA&#xff09;和基于交叉注意力的架构&#xff08;如 Flamingo&#xff09;。混合架构&#xff0c;既提高了训练效率&#xff0c;又增…

基于微信小程序的宿舍报修系统的设计与实现(lw+演示+源码+运行)

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对成果信息管理混乱&#xff0c;出错率高&#xff0c;信息安全性差&am…

SSL证书自动申请脚本

文章目录 介绍&#xff08;直接翻译的&#xff09;特点 准备设置Powershell脚本权限安装Posh-ACME导入Posh-ACME模块设置Email申请DNS操作权限 生成证书查看证书位置效果 介绍&#xff08;直接翻译的&#xff09; PowerShell模块和ACME客户端&#xff0c;用于从具有 ACME 功能…

基于大数据可视化的图书推荐及数据分析系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

腾讯一面-LRU缓存

为了设计一个满足LRU&#xff08;最近最少使用&#xff09;缓存约束的数据结构&#xff0c;我们可以使用哈希表&#xff08;HashMap&#xff09;来存储键值对&#xff0c;以便在O(1)时间复杂度内访问任意键。同时&#xff0c;我们还需要一个双向链表&#xff08;Doubly Linked …

Mac下可以平替paste的软件pastemate,在windows上也能用,还可以实现数据多端同步

Mac平台上非常经典的剪贴板管理工具&#xff1a;「Paste」。作为一款功能完善且易用的工具&#xff0c;「Paste」在实际使用中体现出了许多令人欣赏的特点。但是它是一个收费软件&#xff0c;一年至少要24美元. 现有一平替软件pastemate,功能更加丰富,使用更加方便。 下载地址…

【JAVA报错已解决】 Java.lang.ArrayIndexOutOfBoundsException

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

基于vue框架的传统文化传播网站设计与实现f7r43(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;用户,文化类型,传统文化 开题报告内容 基于Vue框架的传统文化传播网站设计与实现开题报告 一、研究背景 在全球化加速的今天&#xff0c;各国文化相互交融&#xff0c;但也面临着传统文化被边缘化的风险。中国拥有五千年文明史&#…

深夜实验室惊现!AI独立撰写未来论文初稿!

在都市的深夜&#xff0c;当大部分人已进入睡眠之际&#xff0c;某个角落仍旧灯火明亮、活力四射——那是我们的人工智能研究所。此处&#xff0c;自动化机器人和精密算法正在进行激烈的竞赛&#xff0c;致力于撰写可能引领未来变革的前沿科研论文。 科研论文的核心在于其创新…

【数据结构】堆(Heap)详解

在深入了解堆这一重要的数据结构之前&#xff0c;不妨先回顾一下我之前的作品 ——“二叉树详解”。 上篇文章&#x1f449;剖析二叉树&#xff08;Binary Tree&#xff09; 二叉树作为一种基础的数据结构&#xff0c;为我们理解堆以及其他更复杂的数据结构奠定了坚实的基础。它…

Python 从入门到实战30(高级文件的操作)

我们的目标是&#xff1a;通过这一套资料学习下来&#xff0c;通过熟练掌握python基础&#xff0c;然后结合经典实例、实践相结合&#xff0c;使我们完全掌握python&#xff0c;并做到独立完成项目开发的能力。 上篇文章我们讨论了操作目录的相关知识。今天我们将学习一下高级文…

distinct导致sql超时

前言 昨天敲着敲着代码&#xff0c;小杨哥跑过来给我说&#xff0c;快看他们大会议室演示报错了&#xff0c;还是一堆错了。完了啊在演示的时候报错&#xff01;&#xff01;&#xff01;接下来我们分析一下是什么原因吧。 问题分析 查看日志&#xff1a; 从日志打印看明显的…

[大语言模型-论文精读] 大语言模型是单样本URL分类器和解释器

[大语言模型-论文精读] 大语言模型是单样本URL分类器和解释器 目录 文章目录 [大语言模型-论文精读] 大语言模型是单样本URL分类器和解释器目录1. 论文信息2. 摘要3. 引言4. 相关工作A. 网络钓鱼URL检测B. 使用LLMs进行单样本分类 C. LLMs作为分类器的可解释性 5. 论文所提框架…

自媒体人打造视频号爆款短视频其实很简单

最近找我做自媒体起号辅导的非常多&#xff0c;当然今天的方法也很适合我们的自媒体短视频运营。 美国心理学家米勒(Miller)被誉为认知心理学奠基人之一&#xff0c;有关短时记忆容量的研究表明&#xff1a;人的短时记忆保持时间在无复述的情况下只有5~20秒&#xff0c;最长也…

Linux命令:用于处理 XML 文档的强大的命令行工具xmlstarlet 详解

目录 一、概述 二、功能特点 1、查询和过滤 2、修改和更新 3、批处理操作 4、跨平台支持 5、转换和格式化 6、验证和校验 三、 安装 xmlstarlet 四、 基本用法 1、xmlstarlet 的基本语法 2、获取帮助 五、 常用命令 1. ed&#xff08;编辑&#xff09; - 用于编辑…

大型模型智能体:最先进的合作范式、安全与隐私以及未来趋势

摘要—大型模型智能体&#xff08;LM agents&#xff09;&#xff0c;由如 GPT-4 和 DALL-E 2 等大型基础模型驱动&#xff0c;代表了实现人工通用智能&#xff08;AGI&#xff09;的重要一步。LM 智能体展示了自主性、具身性和连接性等关键特征&#xff0c;使其能够在物理、虚…

java在开发中的总结

1.异步执行数据遍历 public static void main(String[] args) {List<Integer> numbers Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);numbers.parallelStream().forEach(i->{System.out.println(i);});}在工作中&#xff0c;我们可以对for循环进行改进&#xff0c;…

C++11:现代C++的演变与提升

目录 前言 一、统一的列表初始化 1、{}初始化 2、std::initializer_list 二、新的声明 1、auto 2、decltype 3、nullptr 三、范围for循环 四、右值引用与移动语义 1. 左值 vs 右值 2、移动构造与移动赋值 3、 move转换 4、完美转发&#xff1a;forward 五、lamb…