innodb间隙锁看这一篇就够啦~

本文详细介绍了InnoDB在RR隔离级别下如何利用MVCC防止幻读,并探讨了间隙锁(Gap Lock)的加锁规则,包括其与行锁、等值查询和范围查询的交互,以及不同情况下产生的锁行为。通过示例展示了间隙锁如何影响INSERT操作,并讨论了其在事务中的作用和限制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

innodb的默认事务隔离级别是rr(可重复读)。它的实现技术是mvcc(MVCC只在读提交可重复读两种隔离级别下工作)。基于版本的控制协议。该技术不仅可以保证innodb的可重复读,而且可以防止幻读。但是它防止的是快照读,也就是读取的数据虽然是一致的,但是数据是历史数据。

为什么说他读的是历史数据的可重复读呢,因为根据这个mvcc的查询规则,新数据他是看不到的,无感知的。

根据mvcc查询和更新的原则:SELECT操作的查询结果要同时满足条件:

1、只会查询版本号小于等于当前版本号的数据作为结果返回,保证了这个数据要么是当前事务修改过的,要么是事务开始之前就已经存在的。

2、行的删除版本要么未定义,要么大于当前事务版本号,这可以确保事务读取到的行,在事务开始之前未被删除

间隙锁是在可重复读的隔离级别下为了解决幻读引入的锁机制。

加锁规则:

  • 原则 1:加锁的基本单位是 next-key lock。希望你还记得,next-key lock 是前开后闭区间。
  • 原则 2:查找过程中访问到的对象才会加锁。limit遍历访问不到的话不会加锁
  • 优化 1:索引上的等值查询,给唯一索引加锁的时候,next-key lock 退化为行锁。
  • 优化 2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock 退化为间隙锁。
  • 唯一索引上的范围查询会访问到不满足条件的第一个值为止。
  • 给普通索引加锁的时候,还会给存在的记录加行锁

加锁规则可以这么理解:

主键/唯一索引查询只有锁住多条记录或者一条不存在的记录的时候,才会产生间隙锁,指定给某条存在的记录加锁的时候,只会加记录锁,不会产生间隙锁;

在id=0,id=5存在的情况下,查询id=3或者查询唯一索引u=3,会产生间隙锁(0,5)

在id=0,id=5,id=10存在的情况下,查询id>3 and id <8,会产生间隙锁(0,5】,(5,10】

在id=0,id=5,id=10存在的情况下,查询唯一索引u>3 and u <8,会产生间隙锁(0,5】,(5,10)

普通索引等值查询,值不存在的情况下,查询c=3,间隙锁为(0,5)

普通索引等值查询,值存在的情况下,查询c=5,间隙锁为(0,5】(5,10)

普通索引范围查询,在id=0,id=5,id=10存在的情况下,查询id>3 and id <6,会产生间隙锁(0,5】,(5,10)

数据库表和数据如下:

CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `c` int(11) DEFAULT NULL,
  `d` int(11) DEFAULT NULL,
  `u` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  UNIQUE KEY `u_index` (`u`),
  KEY `c` (`c`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

                
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值