Mysql锁分类

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 通过看此文,你可以很清晰的了解Mysql InnoDB包含的锁类别,以及不同锁之间的关联及其特定的作用意图。

通过看此文,你可以很清晰的了解Mysql InnoDB包含的锁类别,以及不同锁之间的关联及其特定的作用意图。

行级锁
InnoDB 实现两种行级别标准的锁,它们为 shared locks(S) 和 exclusive locks(X)即 我们常说的共享锁和排它锁,
获取到行共享锁,允许可以读取该行记录,读锁是共享的且允许同一时刻被多线程事务占用
获取到行排它锁,只允许占用X锁的线程事务更新记录,其他线程只能等待

事务T1 以及持有S锁,事务T2也来尝试获取锁,则:
T2 获取S锁,则T2 可以很迅速的拿到锁;
T2 获取X锁,则T2不能立即拿取到锁,需要等待

如果, T1 持有的X锁,则T2 将拿不到任何锁(S, X),只能等待T1释放锁

意向锁(Intention Locks)
多粒度封锁 允许共存行锁和表锁
形如语句:LOCK TABLES T … WRITE 会对特定表进行排他锁。意向锁是表级锁,指示事务稍后对表的行需要特定类型的锁(共享或独占)。两种锁如下:
意向共享锁IS 指示一个事务倾向于在一个表上的单个行加共享锁
意向排它锁IX 指示指示一个事务倾向于在一个表上的单个行加排他锁

例如,

SELECT … FOR SHARE 设置的是 IS lock
SELECT … FOR UPDATES 设置的是一个 IX lock

意向锁如下定义:
1)在一个事务能够获取到一个表的行级共享锁之前,必需先获取一个表的IS或更强的表锁
2)在一个事务能够获取到一个表的行级排他锁之前,必需首先获取一个表的IX锁
那先暂时有个疑问,如果并发多个事务,都是锁定不同的行,那这个表级意向 IX锁是不是成了瓶颈了?问题先放到这,继续往下看。

表级锁的兼容性如下:

条目 X IX S IS
X Conflict Conflict Conflict Conflict
IX Conflict Compatible Conflict Compatible
S Conflict Conflict Compatible Compatible
IS Conflict Compatible Compatible Compatible

如果请求事务与现有锁兼容,则授予该事务锁,但如果与现有锁冲突,则不授予该事务锁。事务一直等待直到冲突锁被释放。如果锁请求与现有锁冲突,并且由于会导致死锁而无法被授予,则会发生错误。

意向锁不会阻塞除全表请求之外的任何东西(例如,LOCK TABLES ... WRITE)。意向锁锁定的主要目的是显示某人锁定了一行,或者准备锁定表中的一行。
此处解答了上述疑问,意向锁IX是不阻塞只是用于表述其他事务有行锁定行为,如果这个时候你想进行全表扫描或全表锁行为,那是不可能的了。

记录锁(Record Locks)
记录锁是一把锁索引记录的锁,例如,SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE; 避免其他事务插入、更新或者删除 where c1=10的行记录

记录锁总是锁住的是索引记录,即便是我们没有定义索引记录,InnoDB 会创建一个隐藏的聚簇索引并使用它来进行记录锁

记录锁的事务数据与使用SHOW ENGINE INNODB STATUS和INNODB monitor output的结果类似:

RECORD LOCKS space id 58 page no 3 n bits 72 index `PRIMARY` of table `test`.`t` 
trx id 10078 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 4; hex 8000000a; asc     ;;
 1: len 6; hex 00000000274f; asc     'O;;
 2: len 7; hex b60000019d0110; asc        ;;

间隙锁(Gap Locks)
间隙锁是对索引记录之间的间隙的锁,或对第一个索引记录之前或最后一个索引记录之后的间隙的锁。例如,SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE; 防止其他事务将值15插入列t.c1,不管列中是否已经存在有这样的值,因为范围中所有现有值之间的间隔都被锁定了,即时表中无c1=15的记录,我们也无法插入这样的数据。

间隙锁可以跨越单个索引,多个索引甚至空
间隙锁是性能和并发性之间权衡的一部分,用于某些事务隔离级别,而不是其他事务隔离级别。
对于使用唯一索引锁定行以搜索唯一行的语句,不需要间隙锁定。(如果搜索条件只包括多列唯一索引的某些列的情况;在这种情况下,确实会发生间隙锁定。)例如,如果id列有一个唯一的索引,下面的语句只对id值为100的行使用索引记录锁,其他会话是否在前面的空格中插入行并不重要
SELECT * FROM child WHERE id = 100;
如果id没有索引,或者索引不是唯一的,那么语句将锁定前面的空格。从这里我们可以看出,如果where条件跟的不是唯一索引,就可能发生间隙锁.

同样值得注意的是,不同的事务可以在间隙上持有冲突锁。例如,事务A可以在一个gap上持有一个共享的gap锁(gap S-lock),而事务B在同一个gap上持有一个独占的gap锁(gap X-lock)。允许存在冲突的间隙锁的原因是,如果从索引中清除一条记录,则必须合并不同事务在记录中持有的间隙锁。

InnoDB中的Gap锁是“纯抑制性的”,这意味着它们的唯一目的是防止其他事务插入到Gap中。间隙锁可以共存。一个事务所采取的间隙锁并不会阻止另一个事务对同一间隙采取间隙锁。共享锁和独占锁之间没有区别。它们之间没有冲突,并且执行相同的功能。
如,

   事务T1: SELECT * FROM child WHERE id > 10 and id < 20;
   事务T2: SELECT * FROM child WHERE id > 15 and id < 30;

事务T1 与 事务T2 相同区间有 16、17、18、19, 都对这些持有gap 锁,只要另一方不对相同区间的值进行insert操作,就不会存在任何问题。

可以显式禁用间隙锁定。如果将事务隔离级别更改为READ COMMITTED,就会禁用之。在这种情况下,对搜索和索引扫描禁用间隙锁,只用于外键约束检查和重复键检查。

使用READ COMMITTED隔离级别还有其他影响。非匹配行的记录锁在MySQL评估WHERE condition之后释放。对于UPDATE语句,InnoDB执行“半一致”读取,这样它将最新提交的版本返回给MySQL,这样MySQL就可以确定该行是否匹配更新的WHERE条件。

Next-Key Locks
next-key锁是索引记录上的记录锁和索引记录前的间隙上的间隙锁的组合。

InnoDB以这样一种方式执行行级锁定:当它搜索或扫描表索引时,它会在遇到的索引记录上设置共享锁或排它锁。 因此,行级锁实际上是索引记录锁。 索引记录上的next-key lock也会影响该索引记录之前的“间隙”。 也就是说,next-key lock是索引记录锁定加上索引记录之前的间隙上的间隙锁定。 如果一个会话在索引中的记录R上具有共享或排他锁,则另一个会话不能在索引顺序中的R之前的间隙中插入新的索引记录。

假设索引包含值10,11,13和20.此索引的可能的next-key lock覆盖以下间隔,其中圆括号表示排除间隔端点,方括号表示包含端点:

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

对于最后一个间隔,next-key lock将间隙锁定在索引中最大值之上,而“supremum”伪记录的值高于索引中实际的任何值。 supremum不是真正的索引记录,因此,实际上,此next-key lock仅锁定最大索引值之后的间隙。如,不能插入21这个新值

默认情况下,InnoDB在REPEATABLE READ事务隔离级别运行。 在这种情况下,InnoDB使用next-key lock进行搜索和索引扫描,从而防止幻影行(幻读)。
幻读一般是,事务1对区间数据进行修改,而事务2在此区间insert了新数据。事务1再次读取的时候,发现仍有新数据未被更新,如同幻觉一样。

插入意向锁(Insert Intention Locks)
插入意向锁是在行插入之前由INSERT操作设置的一种间隙锁定。该锁定表示以这样的方式插入的意图:如果插入到相同索引间隙中的多个事务不插入间隙内的相同位置,则不需要等待彼此。假设存在值为4和7的索引记录。分别尝试插入值5和6的单独事务,在获取插入行上的排它锁之前,每个锁定4和7之间的间隙和插入意向锁,但是不互相阻塞因为行是非冲突的。

以下示例演示了在获取插入记录的独占锁之前采用插入意向锁的事务。该示例涉及两个客户端,A和B.

客户端A创建一个包含两个索引记录(90和102)的表,然后启动一个事务,该事务对ID大于100的索引记录放置独占锁。独占锁包括记录102之前的间隙锁:

mysql> CREATE TABLE child (id int(11) NOT NULL, PRIMARY KEY(id)) ENGINE=InnoDB;
mysql> INSERT INTO child (id) values (90),(102);
mysql> START TRANSACTION;
mysql> SELECT * FROM child WHERE id > 100 FOR UPDATE; 

+-----+
| id  |
+-----+
| 102 |
+-----+

客户端B开始事务以将记录插入间隙。 该事务在等待获取独占锁时采用插入意向锁。

mysql> START TRANSACTION;
mysql> INSERT INTO child (id) VALUES (101);

AUTO-INC Locks
AUTO-INC锁是由插入到具有AUTO_INCREMENT列的表中的事务所采用的特殊表级锁。 在最简单的情况下,如果一个事务正在向表中插入值,则任何其他事务必须等待对该表执行自己的插入,以便第一个事务插入的行接收连续的主键值。
这样开来,如果批量并发的插入大量数据,势必会进行长时间的锁表行为,这样,并发其他的更新或者读取将会是一个问题。这也是mysql自增id带来的烦恼,以及为什么我们需要业务层中生成id的一个原因。

innodb_autoinc_lock_mode配置选项控制用于自动增量锁定的算法。 它允许您选择如何在可预测的自动增量值序列和插入操作的最大并发之间进行权衡。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
28天前
|
SQL 关系型数据库 MySQL
MySQL 锁
MySQL里常见的几种锁
48 3
|
19天前
|
存储 关系型数据库 MySQL
优化 MySQL 的锁机制以提高并发性能
【10月更文挑战第16天】优化 MySQL 锁机制需要综合考虑多个因素,根据具体的应用场景和需求进行针对性的调整。通过不断地优化和改进,可以提高数据库的并发性能,提升系统的整体效率。
25 1
|
1月前
|
关系型数据库 MySQL Java
MySQL数据锁:Record Lock,Gap Lock 和 Next-Key Lock
本文基于 MySQL 8.0.30 版本及 InnoDB 引擎,深入解析三种行锁机制:记录锁(Record Lock)、间隙锁(Gap Lock)和临键锁(Next-key Lock)。记录锁锁定索引记录,确保事务唯一修改;间隙锁锁定索引间的间隙,防止新记录插入;临键锁结合两者,锁定范围并记录自身,有效避免幻读现象。通过具体示例展示了不同锁的作用机制及其在并发控制中的应用。
81 2
|
1月前
|
存储 关系型数据库 MySQL
MySQL数据库锁:共享锁和独占锁
本文详细介绍了`InnoDB`存储引擎中的两种行级别锁:共享锁(S锁)与排他锁(X锁)。通过具体示例展示了这两种锁的工作机制及其在`InnoDB`与`MyISAM`引擎中的表现差异。文章还提供了锁的兼容性矩阵,帮助读者更好地理解锁之间的互斥关系。最后总结了两种锁的特点及适用场景。适合希望深入了解`MySQL`并发控制机制的读者阅读。
28 1
|
19天前
|
存储 关系型数据库 MySQL
MySQL锁,锁的到底是什么?
【10月更文挑战第16天】MySQL 锁锁定的是与数据和资源相关的对象,其目的是为了保证数据的一致性、避免冲突,并在并发环境下合理协调事务或操作的执行。理解锁的对象和意义对于优化数据库性能、处理并发问题至关重要。
48 0
|
2月前
|
监控 关系型数据库 MySQL
MySQL锁机制与解决死锁问题
MySQL锁机制与解决死锁问题
242 5
|
21天前
|
关系型数据库 MySQL 数据库
mysql锁详解
通过理解并合理运用MySQL中的锁机制,开发者可以有效管理数据库并发访问,平衡性能与数据一致性需求。更多关于MySQL锁的深入探讨和最佳实践,请参考专业的数据库管理资源[[深入MySQL锁机制详解
29 0
|
2月前
|
关系型数据库 MySQL 数据库
MYSQL索引的分类与创建语法详解
理解并合理应用这些索引类型,能够有效提高MySQL数据库的性能和查询效率。每种索引类型都有其特定的优势,适当地使用它们可以为数据库操作带来显著的性能提升。
78 3
|
2月前
|
关系型数据库 MySQL 数据库
Mysql的锁
本文介绍了MySQL中表级锁和行级锁的区别,其中MyISAM仅支持表级锁,而InnoDB支持表级锁和行级锁,默认为行级锁。表级锁锁定整个表,实现简单,资源消耗少,但并发度低;行级锁仅锁定相关记录,减少冲突,提高并发度,但加锁开销大。此外,还介绍了共享锁和排他锁的概念及意向锁的作用。
|
2月前
|
存储 SQL 关系型数据库
MySQL 的锁机制,那么多的锁,该怎么区分?
MySQL 的锁机制,那么多的锁,该怎么区分?
37 0