Yuchuan Weng.Miko Tech-Blog.

InnoDB七种类型锁

2018/05/01 Share

本质上,这些都是InnoDB锁机制的问题。总的来说,InnoDB共有七种类型的锁:

  • (1)共享/排它锁(Shared and Exclusive Locks)
  • (2)意向锁(Intention Locks)
  • (3)记录锁(Record Locks)
  • (4)间隙锁(Gap Locks)
  • (5)临键锁(Next-key Locks)
  • (6)插入意向锁(Insert Intention Locks)
  • (7)自增锁(Auto-inc Locks).

基本锁

基本锁:共享锁(Shared Locks:S锁)与排他锁(Exclusive Locks:X锁)

mysql允许拿到S锁的事务读一行,允许拿到X锁的事务更新或删除一行。

加了S锁的记录,允许其他事务再加S锁,不允许其他事务再加X锁;

加了X锁的记录,不允许其他事务再加S锁或者X锁。

mysql对外提供加这两种锁的语法如下:

加S锁:select…lock in share mode

加X锁:select…for update

意向锁(Intention Locks)

==InnoDB为了支持多粒度(表锁与行锁)的锁并存,引入意向锁。==

意向锁是表级锁,可分为意向共享锁(IS锁)和意向排他锁(IX锁)

意向锁产生的主要目的是为了处理行锁和表锁之间的冲突,用于表明“某个事务正在某一行上持有了锁,或者准备去持有锁”。

行锁

记录锁(Record Locks)

记录锁, 仅仅锁住索引记录的一行。

单条索引记录上加锁,record lock锁住的永远是索引,而非记录本身,即使该表上没有任何索引,那么innodb会在后台创建一个隐藏的聚集主键索引,那么锁住的就是这个隐藏的聚集主键索引。所以说当一条sql没有走任何索引时,那么将会在每一条聚集索引后面加X锁,这个类似于表锁,但原理上和表锁应该是完全不同的。

间隙锁(Gap Locks)

区间锁, 仅仅锁住一个索引区间(开区间)。

在索引记录之间的间隙中加锁,或者是在某一条索引记录之前或者之后加锁,并不包括该索引记录本身。

  • next-key锁(Next-Key Locks) record lock + gap lock, 左开右闭区间。默认情况下,innodb使用next-key locks来锁定记录。但当查询的索引含有唯一属性的时候,Next-Key Lock 会进行优化,将其降级为Record Lock,即仅锁住索引本身,不是范围。

  • 插入意向锁(Insert Intention Locks) Gap Lock中存在一种插入意向锁(Insert Intention Lock),在insert操作时产生。在多事务同时写入不同数据至同一索引间隙的时候,并不需要等待其他事务完成,不会发生锁等待。

假设有一个记录索引包含键值4和7,不同的事务分别插入5和6,每个事务都会产生一个加在4-7之间的插入意向锁,获取在插入行上的排它锁,但是不会被互相锁住,因为数据行并不冲突。

注:插入意向锁并非意向锁,而是一种特殊的间隙锁。

行锁的兼容矩阵[^4]

Gap Insert Intention Record Next-Key
Gap 兼容 兼容 兼容 兼容
Insert Intention 冲突 兼容 兼容 冲突
Record 兼容 兼容 冲突 冲突
Next-Key 兼容 兼容 冲突 冲突

表注:横向是已经持有的锁,纵向是正在请求的锁。

由于S锁和S锁是完全兼容的,因此在判别兼容性时只考虑持有的锁与请求的锁是这三种组合情形:X、S和S、X和X、X。

另外,需要提醒注意的是进行兼容判断也只是针对于加锁涉及的行有交集的情形。

分析兼容矩阵可以得出如下几个结论:

  • INSERT操作之间不会有冲突。
  • GAP,Next-Key会阻止Insert。
  • GAP和Record,Next-Key不会冲突
  • Record和Record、Next-Key之间相互冲突。
  • 已有的Insert锁不阻止任何准备加的锁。

自增锁(AUTO-INC Locks)

AUTO-INC锁是一种特殊的表级锁,发生涉及AUTO_INCREMENT列的事务性插入操作时产生。

思路总结

(1)InnoDB使用共享锁,可以提高读读并发;

(2)为了保证数据强一致,InnoDB使用强互斥锁,保证同一行记录修改与删除的串行性;

(3)InnoDB使用插入意向锁,可以提高插入并发;

CATALOG
  1. 1. 基本锁
  2. 2. 意向锁(Intention Locks)
  3. 3. 行锁
    1. 3.1. 记录锁(Record Locks)
    2. 3.2. 间隙锁(Gap Locks)
    3. 3.3. 行锁的兼容矩阵[^4]
  4. 4. 自增锁(AUTO-INC Locks)
  5. 5. 思路总结