MySQL之Gap-Locks与Next-key-Locks
# 介绍
Next-Key Locks 是 MySQL 的 InnoDB 存储引擎的一种锁实现。
MVCC 不能解决幻影读问题,Next-Key Locks 就是为了解决这个问题而存在的。在可重复读(REPEATABLE READ)隔离级别下,使用 MVCC + Next-Key Locks 可以解决幻读问题。而Next-Key就是行锁+Gap锁的组合。
# InnoBD的三种行级锁
- Record Lock:锁定一个记录上的索引,而不是记录本身。如果表没有设置索引,InnoDB 会自动在主键上创建隐藏的聚簇索引,因此 Record Locks依然可以使用。
- Gap Lock:间隙锁,锁定一个范围,但不包括记录本身。GAP锁的目的,是为了防止同一事务的两次当前读,出现幻读的情况。
- Next-Key Lock:1、2组合,锁定一个范围,并且锁定记录本身。对于行的查询,都是采用该方法,主要目的是解决幻读的问题。
# Gap Lock
Gap Lock,又称为间隙锁。存在的主要目的就是为了防止在可重复读的事务级别下,出现幻读问题。
在可重复读的事务级别下面,普通的select读的是快照,不存在幻读情况,但是如果加上for update的话,读取是已提交事务数据,gap锁保证for update情况下,不出现幻读。
以下都是在可重读隔离级别情况下。
test表如下:
id | value |
---|---|
a | 1 |
d | 3 |
g | 6 |
j | 8 |
其中id是主键,value是非唯一索引
# T1
select * from test where num=6 for update;
# T2
insert into test (id, value) VALUES ('a', 3);
1
2
3
4
2
3
4
T1这样的操作会锁定(3,6],(6,8],但是会发现插入操作依旧可以成功,因为虽然Value的区间是锁住了,但是根据id=‘a’这一条让排序在a前面去了
总的来说,锁的间隙是根据B+树排序后的叶子节点之间的区间,不但要看非索引,也会看主键。
- 假如是非索引列,那么将会全表间隙加上gap锁。
- 条件是唯一索引等值检索且记录不存在的情况,我们要考虑,gap lock是防止幻读,那么尝试思考,使用唯一索引所谓条件查找数据for update,如果对应的记录不存在的话,是无法使用行锁的。这时候,会使用gap lock来锁住区间,保证记录不会插入,防止出现幻读。
# 总结
Next-Locks就是结合行锁和间隙锁进行的,主要是用于MVCC出现幻读的情况。
# 参考
在 GitHub 编辑此页 (opens new window)
上次更新: 2024/02/25, 12:11:11