mysql什么时候插入意向锁 mysql的意向锁_加锁

1. 意向锁(Intention Locks)

InnoDB支持多粒度锁(multiple granularity locking),它允许行级锁与表级锁共存,实际应用中,InnoDB使用的是意向锁。
意向锁是指: 未来的某个时刻,事务可能要加共享/排它锁了,先提前声明一个意向。
意向锁有这样一些特点:
(1)首先,意向锁,是一个表级别的锁(table-level locking);

(2)意向锁分为:

  • 意向共享锁(intention shared lock, IS),它预示着,事务有意向对表中的某些行加共享S锁
  • 意向排它锁(intention exclusive lock, IX),它预示着,事务有意向对表中的某些行加排它X锁
  • 举个例子:
    select … lock in share mode,要设置IS锁;
    select … for update,要设置IX锁;

(3)意向锁协议(intention locking protocol)并不复杂:

  • 事务要获得某些行的S锁,必须先获得表的IS锁
  • 事务要获得某些行的X锁,必须先获得表的IX锁

作用: 因为共享锁与排他锁互斥,所以事务 B 在视图对 users 表加共享锁的时候,必须保证:当前没有其他事务持有 users 表的排他锁。当前没有其他事务持有 users 表中任意一行的排他锁 。为了检测是否满足第二个条件,事务 B 必须在确保 users表不存在任何排他锁的前提下,去检测表中的每一行是否存在排他锁。很明显这是一个效率很差的做法,但是有了意向锁之后,情况就不一样了:意向锁的兼容互斥性

主键、非主键唯一索引、普通索引、普通字段四个方面

Net-Key Lock的规则

原则 1:加锁的基本单位是 next-key lock。next-key lock 是前开后闭区间。
原则 2:只有访问到的对象才会加锁。
优化 1:索引上的等值查询,
    命中唯一索,退化为行锁。
    命中普通索引,左右两边的GAP Lock + Record Lock。
优化 2:
    索引上的等值查询,未命中,所在的Net-Key Lock,退化为GAP Lock 。
索引在范围查询: 
    1.等值和范围分开判断。
    2.索引在范围查询的时候 都会访问到所在区间不满足条件的第一个值为止。
    3.如果使用了倒叙排序,按照倒叙排序后,
    检索范围的右边多加一个GAP。
    哪个方向还有命中的等值判断,再向同方向拓展外开里闭的区间。

1. 主键索引

  • 加锁时,会先给表添加意向锁,IX 或 IS;
  • 加锁是如果是多个范围,是分开加了多个锁,每个范围都有锁;(这个可以实践下 id < 20 的情况)
  • 主键等值查询,数据存在时,会对该主键索引的值加行锁 X,REC_NOT_GAP;
  • 主键等值查询,数据不存在时,会对查询条件主键值所在的间隙添加间隙锁 X,GAP;
  • 主键等值查询,范围查询时情况则比较复杂:
    8.0.17 版本是前开后闭,而 8.0.18 版本及以后,修改为了前开后开区间;
    临界 <= 查询时,8.0.17 会锁住下一个 next-key 的前开后闭区间,而 8.0.18 及以后版本,修复了这个 bug。

2. 非主键唯一索引

  • 非主键唯一索引等值查询,数据存在,for update 是会在主键加锁的,而 for share 只有在走覆盖索引的情况下,会仅在自己索引上加锁;
  • 非主键索引等值查询,数据不存在,无论是否索引覆盖,相当于一个范围查询,仅仅会在非主键索引上加锁,加的还是间隙锁,前开后开区间;
  • 在非主键唯一索引范围查询时,不是覆盖索引的时候,会对相应的范围加前开后闭区间,并且如果存在数据,会对对应的主键加行锁;
  • 在非主键唯一索引范围查询时,如果是覆盖索引时,会对所有的后闭区间对应的主键,加行锁;
  • 在非主键唯一索引加锁时,还是存在 next-key 锁住下一个区间的 bug。

3. 普通索引

  • 普通索引等值查询,因为不能确定唯一性,所以即使定位到记录,也是会向后查询,直到查询到不为该值的记录,从而锁定该值的区间;
  • 普通索引的锁也是加载该索引上的,如果涉及到存在的记录,会对该主键加行锁;
  • 普通索引的范围查询,同样出现 next-key 查询下一个区间的 bug。