MySQL几种锁类型和作用总结

本文描述InnoDB引擎下的锁类型

1、共享锁和排他锁(Shared and Exclusive Locks,又称S和X锁)

持有共享锁的事务允许读数据,持有独占锁的事务,可以修改或删除数据。

如果一个事务T1持有了S锁,其他事务T2也可以获取S锁,但是必须等待T1释放S锁,才能获取X锁

2、意向锁(Intention Locks)

意向锁分为意向共享(IS)锁和意向排他(IX)锁。

意向锁是表级锁,一个事务在获得S锁时,必须先获得IS或更高级别的锁,一个事物在获得X锁时,必须先获得IX锁
意向锁兼容矩阵如下:

XIXSIS
XConflictConflictConflictConflict
IXConflictCompatibleConflictCompatible
SConflictConflictCompatibleCompatible
ISConflictCompatibleCompatibleCompatible

意向锁作用:提高并发性能,允许MySQL在加表级锁时不必检查每一行的锁状态,从而减少锁冲突。

3、记录锁(Record Locks)

记录锁锁的是索引记录,即使一张表没有定义索引,InnoDB会创建一个隐藏的聚集索引并使用该聚集索引来锁记录,
例如:

SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE;

将阻止其他事务插入、修改或删除c1=10的记录

4、间隙锁(Gap Locks)

间隙锁锁的是索引之间的间隙,非唯一索引才需要Gap Locks,如果是唯一索引已经确保数据的唯一性,不需要Gap Locks,这个时候只有Record Locks。

举个例子,如果c1是一个唯一索引,下面的SQL语句只会锁c1=10这条记录,而不关心记录之间的间隙

SELECT c1 FROM t WHERE c1 = 10

如果c1不是唯一索引,上面语句会锁间隙,而不仅仅是c1=10的记录间隙锁的目的是只是阻止其他事务往这个间隙插入数据,间隙锁没有共享和独占之说,两个不同的事物可以同时获取相同间隙的间隙锁,这个时候任意一个事务往间隙插入数据都会阻塞。只要没有插入操作,就不会被阻塞。

5、Next-Key Locks

next-key lock是record lock和gap lock的组合。间隙锁是开区间的锁,next-key lock包含了record lock,锁的范围是前开后闭区间。

《MySQL实战45讲》总结道:

我总结的加锁规则里面,包含了两个“原则”、两个“优化”和一个“bug”。

  • 原则 1:加锁的基本单位是 next-key lock。希望你还记得,next-key lock 是前开后闭区间。
  • 原则 2:查找过程中访问到的对象才会加锁。
  • 优化 1:索引上的等值查询,给唯一索引加锁的时候,next-key lock 退化为行锁。
  • 优化 2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock 退化为间隙锁。
  • 一个 bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止。

如何理解索引间隙?

举个例子,按下面脚本构建测试表

create table t (id int primary key , c1 int, key idx_a(c1));
INSERT INTO t (id, c1) VALUES(1, 5);
INSERT INTO t (id, c1) VALUES(7, 7);
INSERT INTO t (id, c1) VALUES(10, 11);
INSERT INTO t (id, c1) VALUES(11, 11);
INSERT INTO t (id, c1) VALUES(13, 13);
INSERT INTO t (id, c1) VALUES(20, 20);

在T1上执行select * from t where c1=11 for update 不提交
在T2上执行

INSERT INTO t (id, c1) VALUES(8, 7); -- 执行被阻塞
INSERT INTO t (id, c1) VALUES(6, 7);  -- 执行成功

为什么同样是c1=11,第一条插入阻塞,第二条插入成功呢?按照前面描述的前开后闭原则,两条应该都要插入成功才对。这就要正确理解T1 next-key lock锁范围。

下面通过一张图体现:

在这里插入图片描述

根据前面非唯一索引等值查询的锁规则结合上图可知,锁的范围是
(7,7)-(13,13)开区间内,任何在这范围内插入数据都会被阻塞。这就解释了,为什么同样是c1=7,id为8的不能插入,id为6的可以插入。

另外可以通过查询 performance_schema.data_locks得到辅证

在这里插入图片描述

可以看到,首先获取了一个意向锁,同时获取了两行c1=11的记录锁(11,10)(11,11),然后获取两个主键的锁10,11 最后获取间隙锁(13,13)。

根据上面分析也可以推导出下面执行的结果
INSERT INTO t (id, c1) VALUES(12, 13); – 执行会被阻塞
INSERT INTO t (id, c1) VALUES(14, 13); – 可以成功插入

此外Innodb还有另外两种锁 Insert Intention Locks、 AUTO-INC Locks

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值