文章插图
我们看上面的兼容性表,也得知表级的 IX 锁和表级的 X 锁是冲突的,所以刚刚好对应上这个场景 。
记录锁【快速解“锁”MySQL,拿下这7把钥匙,便能撬倒面试官】记录锁是对索引记录的锁定,换句话说就是,记录锁只会锁定索引 。每一个表必定会有一个主键索引(用户定义的主键、唯一索引、隐式生成),而该主键索引中的非叶子节点中的记录就是使用该记录锁进行锁定 。
假设执行语句:select * from user where id = 10 for update;
如果 id 是 user 表中的主键,那么在主键索引中,id 为 10 的记录就会被锁定 。并且其他事务想要更新、删除此条记录都会被阻塞,只有等该记录中的记录锁被释放之后,才可以执行其他操作 。
文章插图
除了主键索引之外,InnoDB 中还会有二级索引 。二级索引跟主键索引一样,在使用二级索引作为查询条件时,会将符合条件的二级索引的记录使用记录锁进行锁定,然后再回表将对应的主键索引也使用记录锁进行锁定 。
假设执行语句:select * from user where name = 'c' for update;
如果 id 是 user 表中的主键,name 是 user 表中的二级索引 。则会先将二级索引下的 name = ‘c’ 的索引锁定,然后再进行回表将主键索引为 9 的主键索引锁定 。
文章插图
间隙锁间隙锁(简称为 Gap)是对索引记录之间的间隙的锁定,或者是对第一条索引记录之前的间隙和对最后一条记录之后的间隙的锁 。间隙锁是防止幻读的主要手段之一,幻读是同一个事务在不同的时间执行相同的查询语句,得出的结果集不同 。那么间隙锁是如何防止幻读的呢?实际上就是通过锁定指定的间隙,使得这些间隙无法插入新的记录,从而防止了数据的增长 。
假设我们执行此条语句:select * from user where id > 5 and id < 9 for update;
由于间隙锁的存在,其他事务如果想要插入 id 在 5 和 9 之间的记录是无法成功的,会被阻塞,直到间隙锁释放 。比如想要插入 id 为 6 的记录,就会阻塞,如下图所示(省略部分无关的字段) 。间隙锁跨越的间隙可能为一个值、多个值、甚至为空值 。
文章插图
通过上图我们可以知道:
- (5, 7]:id 为 5 的索引记录与 id 为 7 的索引记录之间的间隙被间隙锁锁定了
- (7, 9]:id 为 7 的索引记录与 id 为 9 的索引记录之间的间隙被间隙锁锁定了
我们上面还说到,间隙锁还在第一条记录的前面和最后一条记录的后面加锁,我们来看看这是什么情况 。
假设我们执行此条语句:select * from user for update;
因为该语句没有使用索引,所以会进行全表扫描 。将扫描到的每一条记录都加上记录锁,并且将所有的间隙也加间隙锁 。最终的加锁情况如下图所示(省略部分无关的字段):
文章插图
每个表中都会存在两个隐式记录:最小记录(infimum),最大记录(supermum)
我们通过上图,可以得出锁定的区间如下:
- (-∞, 5]
- (5, 7]
- (7, 9]
- (9, 10]
- (10, 12]
- (12, +∞)
但是,间隙锁并不是在任何情况下都会使用,它在以下情况并不会使用:
- 隔离级别为 RC、RU 。
- 使用唯一索引进行等值比较获取一条索引记录 。这是因为唯一索引进行等值比较只能获取一条记录,不会出现多条记录的情况,那么也就不会出现多次读取出现不一致的情况 。
Next-Key 锁Next-Key 锁并不是一个难以理解的东西,它本质上就是索引记录上的记录锁和索引记录之间的间隙锁的结合 。
推荐阅读
- 雷电3的大用处!1小时解决旧Mac电脑数据迁移
- Mac电脑上如何找到你的“任务管理器”
- Kbone原理详解与小程序技术选型
- 如何解决路由器静态IP+PPPoE拨号双链路负载分担问题
- 古代所说的“促织”是指现在的什么?
- 阖家幸福和合家幸福有什么区别?
- 太阳能|不烧油不充电 “天津号”太阳能汽车亮相 :真“环保”
- 如何提升店铺等级 如何快速提升淘宝店等级
- 茶具不抽水怎么解决,新紫砂茶具怎么使用
- 聪明女人“三不管” 才能“管”住男人