Mysql中锁类型详解

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: Mysql中锁类型详解

前言


Mysql中除了我们常说的共享锁和排他锁,你还能说出哪些锁类型?今天和大家分享下Mysql在InnoDB引擎下锁的分类。


一、锁的分类


在InnoDB引擎下,锁按照表级锁和行级锁可以如下划分:

61.png


二、锁的特性


1、共享锁和独占锁

InnoDB 实现了标准的行级锁定,其中有两种类型的锁定: 共享(S)锁定和独占(X)锁定。


共享(S)锁允许持有该锁的事务读取一行。

独占(X)锁允许持有锁的事务更新或删除行。


2、意向锁

InnoDB 支持允许行锁和表锁共存的多粒度锁。

意向锁是表级别的锁,它指示事务稍后需要对表中的行使用哪种类型的锁(共享或独占)。


意向锁有2种类型:


意向共享锁(IS):事务在获取表中某行的共享锁之前,必须首先获取表中的 IS 锁或更强的 IS 锁。

意向排他锁(IX):在事务获取表中行的独占锁之前,它必须首先获取表上的 IX 锁/

//当向一个表中的记录添加共享锁时,会先给该表添加一个意向共享锁IS,注意FOR SHARE时Mysql8.0以后的语法
SELECT ... FOR SHARE      
//当向一个表中的记录添加排他锁时,会先给该表添加一个意向排他锁IX
SELECT ... FOR UPDATE


IS锁和IX锁是表级锁,它们的提出仅仅为了在之后加表级别的S锁和X锁时可以快速判断表中的记录是否被上锁,以避免用遍历的方式来查看表中有没有上锁的记录;也就是说,其实IS锁和IX锁是兼容的,IX锁和IX锁是兼容的,IS和IS也是兼容的。


3、标准记录锁 Record Locks

在InnoDB中,行级锁也称为记录锁,都是添加在索引记录上的锁。


标准记录锁的含义是只锁记录不锁间隙。


记录锁始终锁定索引记录,即时表定义时没有索引,对于这种情况,InnoDB 创建一个隐藏的聚集索引,并使用该索引进行记录锁定。


示例:

如果表中存在id=5的记录,执行下面的语句将只会锁定id=5的记录。

//S型标准记录锁
select * from user  where  id = 5  FOR SHARE;
//X型标准记录锁
select * from user  where  id = 5  FOR UPDATE;


4、间隙锁Gap Locks

间隙锁是指在索引记录之间的间隙上的锁,或在第一个索引记录之前或最后一个索引记录之后的间隙上的锁。实际上还是加在索引记录上,不过通过类型区分。


例如:

SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE;

阻止其他事务将15的值插入到列 t.c1中,不管该列中是否已经有这样的值,因为范围内所有现有值之间的间隔都被锁定了。


间隔可能跨越单个索引值、多个索引值,甚至为空。


间隙锁是性能和并发性之间权衡的一部分,只适用于可重复读(Repeatable Read)和串行化(Serializable)隔离级别,核心目的是为了解决幻读问题。


InnoDB 中的间隙锁唯一目的是防止其他事务插入到间隙中。


间隙锁可以共存。一个事务采用的间隙锁不会阻止另一个事务在同一个间隙上采用间隙锁。共享间隙锁和独占间隙锁之间没有区别。它们彼此之间没有冲突,而且它们执行相同的功能。


事务A:

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.02 sec)
//通过范围查询添加间隙锁
mysql> select * from user  where  id > 25  FOR UPDATE;
Empty set


事务B:


mysql> START TRANSACTION;
Query OK, 0 rows affected (0.01 sec)
//通过范围查询添加间隙锁,没有出现锁等待,说明间隙锁可以共存,也就是兼容
mysql> select * from user  where  id > 25  FOR UPDATE;
Empty set


优缺点分析:

优点:解决了事务并发的幻读问题

缺点:因为query执行过程中通过范围查找的话,他会锁定整个范围内所有的索引键值,即使这个键值并不存在。

间隙锁有一个致命的弱点,就是当锁定一个范围键值之后,即使某些不存在的键值也会被无辜的锁定,而造成锁定的时候无法插入锁定键值范围内任何数据。在某些场景下这可能会对性能造成很大的危害。


示例:

如果表中不存在id=5的记录,且事务隔离级别为默认的RR,则会给id=5所在的间隙加锁。

START TRANSACTION;
select * from user  where  id = 5  FOR UPDATE;


5、临键锁 Next-Key Locks

临键锁(Next-Key Locks)是索引记录上的记录锁和索引记录前的间隙锁的组合。

理解为Record Lock+索引前面的Gap Lock。记住了,锁住的是索引前面的间隙。比如一个索引包含值,10,11,13和20。那么,间隙锁的范围如下


(negative infinity, 10]
(10, 11]
(11, 13]
(13, 20]
(20, positive infinity)


Next-Key Locks的范围是左开右闭。默认右边的记录也会加锁。


临键锁(Next-Key Locks)适用的事务隔离级别和间隙锁(Gap Locks)保持一致:可重复读(Repeatable Read)和串行化(Serializable)


InnoDB 执行行级锁定的方式是,当它搜索或扫描表索引时,它对遇到的索引记录设置共享锁或排他锁。因此,行级锁实际上是索引记录锁。索引记录上的临键锁(Next-Key Locks)也会影响该索引记录之前的“间隔”。也就是说,临键锁(Next-Key Locks)是索引标准记录锁(Record Locks)加上位于索引记录之前的间隙上的间隙锁(Gap Locks)。


60.png


6、插入意向锁 Insert Intention Locks

官方名称:LOCK_INSERT_INTENTION,也称为插入意向锁:事务在等待时也需要在内存中生成一个锁结构,表明有事务想在某个间隙中插入新记录,但是现在处于等待状态。如下图所示:

59.png

插入意向锁是一种由插入行之前的 INSERT 操作设置的间隙锁。这个锁表明插入的意图,如果插入到同一索引间隙中的多个事务没有插入到间隙中的同一位置,那么它们就不需要等待对方。假设有值为4和7的索引记录。分别尝试插入值5和6的独立事务,每个事务在获得插入行上的独占锁之前使用插入意向锁锁锁定4和7之间的间隙,但不会相互阻塞,因为行是非冲突的。


只有向间隙锁锁定的间隙中间插入数据时,才会添加插入意向锁。并且插入意向锁是一种短锁,当插入语句执行完成后会立即释放,而不是等到事务提交或回滚再释放。


7、自增主键锁 AUTO-INC Locks

AUTO-INC 锁是一种特殊的表级锁,由插入具有 AUTO_INCREMENT 列的表的事务获取。在最简单的情况下,如果一个事务正在向表中插入值,则任何其他事务必须等待向该表中执行自己的插入操作,以便由第一个事务插入的行接收连续的主键值。


这也是多个事务批量插入数据时,最后仍然可以保证表的自增主键是连续的原因。


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

InnoDB 支持对包含空间数据的列进行空间索引(参见第11.4.9节“优化空间分析”)。为了处理涉及空间索引的操作的锁定,next-key 锁定不能很好地支持 REPEATABLE READ 或 SERIALIZABLE 事务隔离级别。在多维数据中没有绝对排序的概念,因此不清楚哪个是“下一个”键。为了支持对具有 SPATIAL 索引的表的隔离级别,InnoDB 使用谓词锁。空间索引包含最小外接矩形(MBR)值,所以 InnoDB 通过对用于查询的 MBR 值设置谓词锁来强制对索引进行一致的读取。其他事务无法插入或修改与查询条件匹配的行。


主要是针对空间索引加锁的优化。


9、长锁和短锁

如果锁获取之后直到事务提交后才释放,这种锁称为长锁,比如间隙锁(Gap Locks)。

如果锁在操作完成之后就被释放,这种锁称为短锁,比如插入意向锁 (Insert Intention Locks)。


三、锁的兼容性


1、表级锁的兼容性

58.png

说明:


读读兼容,读写不兼容,写写不兼容

意向锁之间相互兼容


2、行级锁的兼容性

57.png

说明:


标准记录锁(Record)和临键锁(Next-Key)之间符合读写锁的规律:读读兼容,读写和写写不兼容。

间隙锁(Gap)的目的是防止其他事务插入数据到索引间隙中,所以Gap锁会阻塞插入意向锁。

间隙锁(Gap)之间相互兼容

间隙锁(Gap 和 临键锁(Next-Key)相互兼容。

核心就是如果锁定了实际的索引记录,则需要遵循读写锁的规则的兼容性。


总结


本文主要是对Mysql的InnoDB下的锁的相关类型做了介绍。

重点需要关注如下几点:

1、行级锁和表级锁的分类。

2、各种锁的作用及特性,以及适用的隔离级别。

3、各种锁相互间的兼容性。

锁的兼容性本质上还是读写锁的那一套,无非就是添加了间隙锁和插入意向锁,核心就是用来解决幻读问题。


相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
3月前
|
SQL 关系型数据库 MySQL
MySQL 锁
MySQL里常见的几种锁
59 3
|
20天前
|
存储 关系型数据库 MySQL
mysql怎么查询longblob类型数据的大小
通过本文的介绍,希望您能深入理解如何查询MySQL中 `LONG BLOB`类型数据的大小,并结合优化技术提升查询性能,以满足实际业务需求。
80 6
|
2月前
|
分布式计算 关系型数据库 MySQL
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型 图像处理 光通信 分布式计算 算法语言 信息技术 计算机应用
60 8
|
3月前
|
关系型数据库 MySQL
用dbeaver创建一个enum类型,并讲述一部分,mysql的enum类型的知识
这篇文章介绍了如何在DBeaver中创建MySQL表的枚举(ENUM)字段,并探讨了MySQL中ENUM类型的一些行为特点,例如ENUM值的默认排序和在插入重复值时的表现。
64 1
用dbeaver创建一个enum类型,并讲述一部分,mysql的enum类型的知识
|
3月前
|
存储 关系型数据库 MySQL
优化 MySQL 的锁机制以提高并发性能
【10月更文挑战第16天】优化 MySQL 锁机制需要综合考虑多个因素,根据具体的应用场景和需求进行针对性的调整。通过不断地优化和改进,可以提高数据库的并发性能,提升系统的整体效率。
160 1
|
3月前
|
关系型数据库 MySQL Java
MySQL数据锁:Record Lock,Gap Lock 和 Next-Key Lock
本文基于 MySQL 8.0.30 版本及 InnoDB 引擎,深入解析三种行锁机制:记录锁(Record Lock)、间隙锁(Gap Lock)和临键锁(Next-key Lock)。记录锁锁定索引记录,确保事务唯一修改;间隙锁锁定索引间的间隙,防止新记录插入;临键锁结合两者,锁定范围并记录自身,有效避免幻读现象。通过具体示例展示了不同锁的作用机制及其在并发控制中的应用。
306 2
|
3月前
|
存储 关系型数据库 MySQL
MySQL数据库锁:共享锁和独占锁
本文详细介绍了`InnoDB`存储引擎中的两种行级别锁:共享锁(S锁)与排他锁(X锁)。通过具体示例展示了这两种锁的工作机制及其在`InnoDB`与`MyISAM`引擎中的表现差异。文章还提供了锁的兼容性矩阵,帮助读者更好地理解锁之间的互斥关系。最后总结了两种锁的特点及适用场景。适合希望深入了解`MySQL`并发控制机制的读者阅读。
101 1
|
2月前
|
关系型数据库 MySQL Java
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
36 0
|
4月前
|
监控 关系型数据库 MySQL
MySQL锁机制与解决死锁问题
MySQL锁机制与解决死锁问题
364 5
|
3月前
|
存储 关系型数据库 MySQL
MySQL锁,锁的到底是什么?
【10月更文挑战第16天】MySQL 锁锁定的是与数据和资源相关的对象,其目的是为了保证数据的一致性、避免冲突,并在并发环境下合理协调事务或操作的执行。理解锁的对象和意义对于优化数据库性能、处理并发问题至关重要。
105 0