MySQL系列(四)InnoDB存储引擎の锁

摘要

本文基于MySQL5.7官方文档介绍InnoDB所有的锁类型。

到底有多少种锁?

以下总结自MySQL 5.7 官方文档,其中第6-8种锁还是第一次听说。

  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

  8. Predicate Locks for Spatial Indexes(用于空间索引的谓词锁)

共享锁和排它锁——Shared and Exclusive Locks

InnoDB最大的特性在于“行锁”。在并发访问数据的情况下,这将会带来非常大的性能提升。因为表中的数据可以根据要读的行来分别进行加锁,InnoDB不需要锁住整个表。这两种类型的行锁又称为:shared (S) locks and exclusive (X) locks。下面是对这两种锁的介绍,以及互斥规则。

  • 共享锁:允许一个事务锁住它要“读”的行。
    • 事务T1:持有行 r 的(S)锁。
    • 事务T2:
      • 请求行 r 的(S)锁将立即成功。
      • 请求行 r 的 (X)锁将被阻塞。
  • 排它锁:允许一个事物锁住它要“Updatedelete”的行。
    • 事务T1:持有行 r 的(X)锁。

    • 事务T2:无论持有哪种锁都会被阻塞,直到T1释放排它锁。

意向锁——Intention Locks

InnoDB支持“多粒度加锁”方式,简单来说,就是可以支持对表加锁和对行加锁。

含义:意向锁属于“表锁”级别。它表示一个事务“已经”对表中某一行加了锁,或者说“将要”对某一行加锁。意向锁不会阻塞其他事务,除非把整个表都锁住的语句:LOCK TABLES ... WRITE

  • 意向共享锁(IS):表明一个事务倾向于对表中某一行加(S)锁。

  • 意向排它锁(IX):表明一个事务倾向于对表中某行加(X)锁。

例如,SELECT ... LOCK IN SHARE MODE 设置IS锁,而SELECT ... FOR UPDATE设置IX锁。

意向锁加锁原则如下:

  • 对某行加S锁之前必须先获得IS锁或者IX锁。

  • 对某行加X锁之前必须先获得IX锁。

锁的兼容性如下:无论是IX或IS,都与其他IX或IS兼容。

XIXSIS
X冲突冲突冲突冲突
IX冲突兼容冲突兼容
S冲突冲突兼容兼容
IS冲突兼容兼容兼容

一个事务能否获取到锁,取决于这个锁是否与表中已经存在的锁兼容。如果兼容,那么将申请成功;否则,事务只能等待其他人释放掉锁。

记录锁——Record Locks

含义:对单个索引记录加锁,就是InnoDB真正使用的“行锁”。它只会锁住索引记录,如果表里面没有索引,那么InnoDB会隐式的创建一个聚集索引。

例如,SELECT * FROM child WHERE id = 100;将只会使用记录锁。

Tips:这里额外补充一点,InnoDB会从上到下的顺序创建聚集索引:

  1. 主键id列。
  2. non-null且unique约束的列。
  3. 前两种类型的列都没有,那么InnoDB将隐式创建一个聚集索引列。

间隙锁——Gap Locks

含义:只锁住Records之间的间隙,此外也可以锁住第一条记录之前或者最后一条记录之后的间隙。但不会锁定记录本身。

例如:SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE;将会锁住10-20之间的值,这样可以防止其他事务尝试插入一个值为15的数据。

有两点细节需要注意:

  1. Gap Lock只存在于REPEATABLE READREAD COMMITTED并发时不会使用。
  2. 同一个Gap可以被多个事务持有S或X锁。例如事务A持有了一个Gap的(gap S-lock),事务B也可以对这个Gap持有(gap X-lock)。

Next-Key Locks

含义:Record Lock + Gap Lock的组合。即锁住所有满足条件的记录和其中第一条记录之前的“一个”及之后的“所有”间隙。

例如,表中有数据10, 11, 13, 20。next-key lock可以锁住的区间有:

(-∞, 10]

(10, 11]

(11, 13]

(13, 20]

(20, +∞)

InnoDB通过这个锁来解决“幻读”问题(MySQL官方将我之前理解的“不可重复读”定义为幻读,所以其实它们俩是同一东西)。

实例1:假如表中有数据1, 2, 5,事务A执行SELECT * FROM t WHERE a > 2 FOR UPDATE。next-key lock会对(2, +∞)这个区间加(X)锁,因此在这区间内的Insert都是不允许的,从而解决了幻读问题。

Insert Intention Locks

含义:一种当执行“插入一行”操作时设置的gap lock。

AUTO-INC Locks

含义:一种当事务插入AUTO_INCREMENT列时会设置的“表级别”锁。


参考资料

  1. MySQL5.7官方文档
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_ʙᴀɴɢ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值