MySQL-InnoDB之Gap Lock、Next-Key Lock、Record Lock解析

锁概述

MySQL InnoDB支持三种行锁定方式:

  1. 行锁(Record Lock):锁直接加在索引记录上面,锁住的是key。
  2. 间隙锁(Gap Lock):锁定索引记录间隙,确保索引记录的间隙不变。间隙锁是针对事务隔离级别为可重复读或以上级别而已的。可以防止幻读的发生。
  3. Next-Key Lock :行锁和间隙锁组合起来就叫Next-Key Lock。

  默认情况下,InnoDB工作在可重复读隔离级别下,并且会以Next-Key Lock的方式对数据行进行加锁,这样可以有效防止幻读的发生。

  Next-Key Lock是行锁和间隙锁的组合,当InnoDB扫描索引记录的时候,会首先对索引记录加上行锁(Record Lock),再对索引记录两边的间隙加上间隙锁(Gap Lock)。加上间隙锁之后,其他事务就不能在这个间隙修改或者插入记录。

  Gap Lock在InnoDB的唯一作用就是防止其他事务的插入操作,以此防止幻读的发生。

行锁(Record Lock)

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

什么时候使用行锁?

当增删改查匹配到索引时,Innodb 会使用行级锁。

如果没有匹配不到索引,那么就会直接使用表级锁。

间隙锁(Gap Lock)

  在索引记录之间的间隙中加锁,或者是在某一条索引记录之前或者之后加锁,并不包括该索引记录本身。gap lock的机制主要是解决可重复读模式下的幻读问题,关于幻读的演示和gap锁如何解决了幻读。

打开间隙锁设置

  首先查看 innodb_locks_unsafe_for_binlog 是否禁用:

show variables like 'innodb_locks_unsafe_for_binlog';

  查看结果:
在这里插入图片描述

  innodb_locks_unsafe_for_binlog:默认值为OFF,即启用间隙锁。因为此参数是只读模式,如果想要禁用间隙锁,需要修改 my.cnf(windows是my.ini) 重新启动才行。

# 在 my.cnf 里面的[mysqld]添加
[mysqld]
innodb_locks_unsafe_for_binlog = 1

Next-Key Lock

  间隙锁(Gap Lock)是Innodb在可重复读提交下为了解决幻读问题时引入的锁机制,幻读的问题存在是因为新增数据记录操作,这时如果进行范围查询的时候(加锁查询),会出现不一致的问题,这时使用不同的行锁已经没有办法满足要求,需要对一定范围内的数据进行加锁,间隙锁就是解决这类问题的。

临键锁的主要目的,也是为了避免幻读(Phantom Read)。如果把事务的隔离级别降级为RC,临键锁则也会失效

  在可重复读隔离级别下,数据库是通过行锁和间隙锁共同组成的(next-key lock),来实现的加锁规则有以下特性:

  1. 加锁的基本单位是(next-key lock),它是前开后闭原则
  2. 查询过程中访问的对象会增加锁;
  3. 索引上的等值查询–给唯一索引加锁的时候,next-key lock升级为行锁;
  4. 索引上的等值查询–向右遍历时最后一个值不满足查询需求时,next-key lock 退化为间隙锁;
  5. 唯一索引上的范围查询会访问到不满足条件的第一个值为止。

锁的拓展

表级锁

  表级锁可以分为:表锁元数据锁意向锁三种。

表锁

  表锁,顾名思义就是对某个表加锁。

  那什么时候会使用表锁呢?

  1. 一般情况是对应的存储引擎没有行级锁(例如:MyIASM);
    因为对应存储引擎不支持行锁,所以只能是使用更粗粒度的锁来实现,这也比较好理解。
  2. 对应的 SQL 语句没有匹配到索引。
    如果存储引擎支持行锁,但对应的 SQL 就没有使用索引,那么此时也是会全表扫描,那此时也是会使用表锁。
元数据锁

  元数据,指的是我们的表结构这些元数据。元数据锁(Metadata Lock)自然是执行 DDL 表结构变更语句时,对表加上的一个锁了。

  那什么时候会使用元数据锁这个表级锁呢?

  1. 当对一个表数据做增删改查操作的时候,会加上 MDL 读锁;
  2. 当我们要对表结构做变更时,就会加 MDL 写锁。
意向锁

  意向锁是指,未来的某个时刻,事务可能要加共享/排它锁了,先提前声明一个意向。

  InnoDB为了支持多粒度锁机制(multiple granularity locking),即允许行级锁与表级锁共存,而引入了意向锁(intention locks)。

  意向锁是一个表级别的锁(table-level locking)

  意向锁又分为:

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

  但是从实现算法上来分的话,Innodb的三种行锁分别是:间隙锁、行锁和Next-Key Lock。
  
参考:
https://www.shuzhiduo.com/A/KE5QYmx05L/
https://www.cnblogs.com/crazylqy/p/7773492.html
https://www.jianshu.com/p/32904ee07e56
MySQL的锁机制 - 记录锁、间隙锁、临键锁
Mysql之Innodb锁机制详解
深入分析MySQL行锁加锁规则讲述数据存在/不存在情况下加锁的范围

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

冲上云霄的Jayden

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

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

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

打赏作者

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

抵扣说明:

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

余额充值