-
临键锁(Next-Key Locks)
有时候我们既想 锁住某条记录 ,又想 阻止 其他事务在该记录前边的 间隙插入新记录 ,所以InnoDB就提出了一种称之为 Next-Key Locks 的锁,官方的类型名称为:
LOCK_ORDINARY ,我们也可以简称为next-key锁 。Next-Key Locks是在存储引擎 innodb 、事务级别在 可重复读 的情况下使用的数据库锁,innodb默认的锁就是Next-Key locks
相当于记录锁+间隙锁
间隙锁是2行记录的开区间中不允许插入数据
临键锁是2行记录的闭区间不允许操作数据
- 案例
# 开启1个新的连接,开启1个新的事务
begin;
# 获取临键锁
select * from student where id <=8 and id > 3 for update;
# 开启1个新的连接,开启1个新的事务
begin;
# 在区间内去获取1个共享锁,获取失败,因为在第1个连接中已经获取了1个临键锁
select * from student where id = 15 lock in share mode;
# 向区间内插入1条数据,插入失败
insert into student(id, name, class) values(12, "Tom", "aaa");
-
插入意向锁(Insert Intention Locks)
:是1中行级锁,不是意向锁,也不是表级锁
我们说一个事务在 插入 一条记录时需要判断一下插入位置是不是被别的事务加了 gap锁 ( next-key锁也包含 gap锁 ),如果有的话,插入操作需要等待,直到拥有 gap锁 的那个事务提交。
但是InnoDB规定事务在等待的时候也需要在内存中生成一个锁结构,表明有事务想在某个 间隙 中 插入 新记录,但是现在在等待。InnoDB就把这种类型的锁命名为 Insert Intention Locks ,
官方的类型名称为:LOCK_INSERT_INTENTION ,我们称为 插入意向锁 。插入意向锁是一种 Gap锁 ,不是意向锁,在insert操作时产生。
插入意向锁是在插入一条记录行前,由 INSERT 操作产生的一种间隙锁 。
事实上插入意向锁并不会阻止别的事务继续获取该记录上任何类型的锁
- 案例
# 开启1个新的连接,开启1个事务
begin;
# 为某个不存在的行添加1个共享锁,即间隙锁
select * from student where id= 5 lock in share mode;
# 开启第2个新的连接,开启1个事务
begin;
# 向区间内插入1条数据,处于阻塞状态
insert into student(id, name, class) value(6, "gou", "man");
# 开启第3个新的连接,开启1个事务
begin;
# 向区间内插入1条数据,处于阻塞状态
insert into student(id, name, class) value(7, "gou", "man");
# 第2个连接和第3个连接中,执行插入语句时,mysql会自动生成1个插入意向锁,表示该事务有1个插入的意向
# 当第1个连接中的事务提交后,即释放锁后,这2条插入语句如果还没有超时,则会执行成功
# 这2条插入语句间的关系是兼容的