Innodb间隙锁


前言

提示:演示间隙锁是如何工作的,以及如何解决幻读的


一、锁的算法

1. 三种算法

  1. Record Lock (读已提交用的是这个)
  2. Gap Lock
  3. Next-Key Lock : Record Lock + Gap Lock (可重复读用的是这个)

2. Next-Key Lock锁住的范围

假设一个索引有10,11,13,20 这四个值,那么锁住的范围如下:

  • (负无穷,10]
  • (10,11]
  • (11,13]
  • (13,20]
  • (20,正无穷]

二、示例 (可重复读隔离级别)

1.当查询的索引有唯一属性时

1. 准备数据

代码如下(示例):

create table lock_next_key_unikey(a int primary key);
insert into lock_next_key_unikey (a) values(1),(2),(5);

2.演示

A事务:

// 开启事务
begin ;
// 对 a = 5 上X锁
select * from lock_next_key_unikey where a = 5 for update ;

B事务:

// 开启事务
begin ;
// 插入 a = 4 (这个会成功)
insert into lock_next_key_unikey (a) values(4);

说明: 之所以会插入成功的原因是:当查询的索引含有唯一属性时,如果是联合唯一索引,需要全部查询,则Next-Key Lock降级为行锁,仅锁住了a=5这一行。不影响其他行的读写。


2.当查询的索引没有唯一属性时

1. 准备数据

代码如下(示例):

create table lock_next_key_key(a int , b int ,PRIMARY key(a),key(b));

insert into lock_next_key_key (a,b) values (1,1),(3,1),(5,3),(7,6),(10,8);

2.演示

1.锁住这行

加锁都是对索引加的。
A事务:

// 开启事务
begin ;
// 对 b = 3 上X锁
select * from lock_next_key_key where b = 3 for update ;

而如果是
select * from lock_next_key_key where b = 1 for update ;
则会锁住多行。

B事务:

// 开启事务
begin ;
// 获取a=5这行数据的S锁 , 因为A对它有X锁,故等待
select * from lock_next_key_key where a = 5 lock in share mode ;

C事务:

// 开启事务
begin ;
// 插入数据 (阻塞)
insert into lock_next_key_key (a,b) values(4,2);
insert into lock_next_key_key (a,b) values(6,5);

说明: 这两个插入都会被阻塞,因为:当查询的是辅助索引,且不是唯一索引时,会锁住前后两个区间,这里锁住的辅助索引对应的区间是(1,3),(3,6),当然b=3这个也是会被锁住的,因此b=2,5都在这个被锁住的区间,因此插入是阻塞的。

3. 锁住的是聚集索引和辅助索引对应的行和范围

与查询里面是否包含什么无关,与涉及到的行有关,我们增加一列:
alter table lock_next_key_key add column c int ;
update lock_next_key_key set c = b ;
然后开启一个事务,并
select * from lock_next_key_key where c = 3 for update ;
则效果和
select * from lock_next_key_key where b = 3 for update ;
是一样的,锁住的都是行对应的索引的对应的索引区间。


总结

以上也就说明了为什么可重复读可以解决幻读,因为锁住了行对应的区间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值