MySQL深度解析---可重复读的间隙锁

InnoDB的默认事务隔离级别是可重复读

一、幻读

1.SQL场景复现

建一个测试表:

CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `c` int(11) DEFAULT NULL,
  `d` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `c` (`c`)
) ENGINE=InnoDB;

insert into t values(0,0,0),(5,5,5),
(10,10,10),(15,15,15),(20,20,20),(25,25,25);

2. 概念引入

写锁(更新锁):在对一行更新时(或者在select后加for update),对该行加写锁,加锁期间其他行不可以查询或修改该行。

间隙锁(Gap Lock):间隙锁 锁的是两个值之间的空隙。比如:比如文章开头的表t,初始化插入了6个记录,这就产生了7个间隙。
间隙锁特性: 跟间隙锁产生冲突的,是“往这个间隙中插入一条记录”的操作。间隙锁之间不存在冲突关系。 也就是说,间隙锁可以重复叠加。这个特性可能会导致死锁问题。
间隙锁是在可重复读隔离级别下才会生效的
PS:如果把隔离级别设置为读提交的话,就没有间隙锁了。但同时,你要解决可能出现的数据和日志不一致问题,需要把binlog格式设置为row。这也是现在不少公司使用的配置组合。

在这里插入图片描述

3.场景分析

在这里插入图片描述
可以看到,session A里执行了三次查询,分别是Q1、Q2和Q3。它们的SQL语句相同,都是select * from t where d=5 for update。查所有d=5的行,而且使用的是当前读,并且加上写锁。

MySQL中,带有for update 的select语句会给扫描过的每一行记录加写锁
MySQL中,给记录加写锁时,会把该记录两边的间隙加间隙锁

因此,T1时刻,sessionA执行的语句将给表t 所有的行加写锁,T2时刻,sessionB的更新语句由于表t整个都加了写锁,所以会等到sessionA事务提交 释放写锁后 才会执行。
T4时刻,sessionC的插入语句由于表t整个都加了间隙锁,所以无法插入,会等到sessionA事务提交后 释放间隙锁后 才会执行插入操作。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值