原来 MySQL 锁机制长这样

一、锁分类

1.按思想划分

  1. 乐观锁
    老乐观了,乐观锁认为一般情况下数据不会造成冲突,所以在数据进行提交更新时才会对数据的冲突与否进行检测。类比 CAS
  2. 悲观锁
    老悲观了,在整个数据处理过程中,将数据处于锁定状态。类比synchronized

2.按粒度划分

  1. 行锁
  2. 页锁
  3. 表锁

3.按类型划分

  1. 共享锁(读锁)
  2. 排他锁(写锁)

二、MyISAM

1.加锁特点

MyISAM采用表锁,MyISAM在执行查询、更新操作时,会对所有涉及的表格加上读锁或写锁

2.并发插入

1.MyISAM并发插入官方说明
在这里插入图片描述
2. 解释

  • MyISAM 存储引擎支持并发插入,目的在于减少读写锁之间的争用
  • 如果表格数据文件之间没有空洞(即中间没有删除的数据),在执行SELECT 语句得同时,可以执行 INSERT 语句将数据行添加至表的末尾(即并发插入
  • 如果有多个 INSERT 语句,它们将被排队并依次执行,同时执行 SELECT 语句。并发插入的结果可能不会立即可见

3.concurrent_insert 系统变量

  • 默认为 AUTO(or 1),在没有空洞的情况下支持并发插入
  • NEVER (or 0),禁用并发插入
  • ALWAYS (or 2),即使对于有空洞的表,也允许在表末尾进行并发插入

4. MyISAM 锁调度

对于仅使用表级锁的存储引擎(如 MyISAMMEMORYMERGE),写进程优先级高于读进程,尽管读进程在队列的头部,写进程也会插队
在这里插入图片描述

  • 通过设置系统变量 low-priority-updates=1,所有的 INSERT、UPDATE、DELETELOCK TABLE WRITE 语句都将等待,直到受影响的表上没有挂起的 SELECTLOCK TABLE 读操作。
  • 通过指定 INSERT、UPDATE、DELETE 语句的 LOW_PRIORITY 属性,降低该语句的优先级。

三、 InnoDB

InnoDB支持 行锁表锁

1. 按锁的类别划分

  1. 共享(S)锁排他(X)锁

事务 T1 持有 r 行上的共享锁,此时另一个事务 T2r 行上的锁的请求处理如下:

  • 事务 T2r 行请求 S可以被立即授予,因此,T1T2 都会获得 r 行S
  • 事务 T2r 行请求 X不能被立即授予

如果事务 T1 持有 r 行上的排他(X)锁,那么另一个事务 T2 的请求不能立即被授予 r 行上任何一种类型的锁。此时事务 T2 必须等待事务 T1 释放其在 r 行上的X锁

读读兼容读写互斥

  1. 意向锁

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

为了在多个粒度级别上实现锁,InnoDB使用了意向锁意向锁表级锁,它指示事务稍后需要对表中的一行使用哪种类型的锁(共享锁排他锁)。

  • 意向共享(IS)锁
    表示事务打算在表中的单个行上设置 共享锁
  • 意向排他(IX)锁
    表示事务打算在表中的单个行上设置一个 排他锁

锁兼容情况如下:

X IX S IS
X N N N N
IX N Y N Y
S N N Y Y
IS N Y Y Y
  1. Record Locks
    行锁 锁的是 索引 记录,当执行如下SQL时:
SELECT id FROM student WHERE id = 1;

会对id=1的索引进行加锁,防止其他事务对其插入、更新或删除。

  1. Gap Locks

间隙锁是在索引记录之间的间隙上的锁,或者是在第一个索引记录之前或最后一个索引记录之后的间隙上的锁。

例如,

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

若有其他事务向t.c1列插入值15,是不允许的,因为当前范围内(10-20)的间隙已被上了间隙锁

对于使用唯一索引进行搜索时,不会产生间隙锁,若在联合索引进行搜索的情况下,会产生间隙锁。

例如:

SELECT * FROM child WHERE id = 100;
  • 如果id列是唯一索引,那么上面的语句只对id=100的行使用行锁,不会产生间隙锁
  • 如果id列没有索引,或者有一个二级索引,那么该语句将锁定前面的间隙

在READ COMMITED(读已提交)的隔离级别下,间隙锁会被显示的禁用

  1. Next-Key Locks

Next-Key LocksRecord LocksGap Locks 组合而成

例子:当事务 T1r行 加 共享 或 排他锁时,同时会对 r行 前的间隙加 间隙锁,此时,另一个事务 T2 无法在 r行 之前插入新的索引记录。
假设一个索引包含值10、11、13和20。该索引可能的 Next-Key Locks覆盖以下区间:

(-∞, 10]
(10, 11]
(11, 13]
(13, 20]
(20, +∞)
对于最后一个间隔,Next-Key Locks 锁定了索引中最大值之上的间隙和“正无穷”伪记录,该伪记录的值高于索引中任何实际值。其并不是一个真正的索引记录,因此,实际上,这个 Next-Key Locks 只锁定最大索引值后面的间隙

默认情况下,InnoDB操作在 可重复读(REPEATABLE READ) 事务隔离级别。在这种情况下,InnoDB使用Next-Key Locks进行搜索和索引扫描,这样可以防止幻读

参考文献

MySQL 官方文档
weblee
tianye_guazi

猜你喜欢

转载自blog.csdn.net/qq_41917138/article/details/114399059