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);

该表除了主键id,还有索引c。

问下面的语句序列,是怎么加锁的,加的锁又是什么时候释放的呢?

begin;
select * from t where d = 5 for update;
commit;

这条语句会命中d=5这一行,对应主键id=5,因此在select语句执行完成后,id=5这一行会加一个写锁,并且由于两阶段锁协议,这个写锁会在执行commit语句的时候释放。

由于字段d上没有索引,因此这条查询语句会做全表扫描,那么,其他被扫描的不满足的行记录会不会被加锁?

幻读现象

如果旨在id=5这一行加锁,而其他行不加锁,在下面这个情况下:

session A执行了三次当前读,并且加上了写锁。

幻读指的是一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行。

幻读与不可重复读的区别

在同一个事务中,两次读取到的数据不一致的情况称为幻读和不可重复读。幻读是针对insert导致的数据不一致,不可重复读是针对 delete、update导致的数据不一致。

1、在可重复读隔离级别下,普通的查询是快照读,是不会看到别的事务插入的数据的。

2、session B的修改结果被session A之后的select语句用当前读看到,不能称为幻读。幻读仅仅指"新插入的行"

幻读带来的问题

1、破坏语义。

session A在T1就说了,把d=5的行锁住,不准别的事务进行读写,此时被破坏。

因为如果我们这时插入d=5的数据,这条新的数据不在锁的保护范围之内。

2、数据一致性问题

锁的设计是为了保证数据的一致性,不止是数据库内部数据状态在此刻的一致性,还包含了数据和日志在逻辑上的一致性。

即使给所有行加上了锁,也避免不了幻读,这是因为给行加锁的时候,这条记录还不存在,没法加锁 。

也就是说即使把所有的记录都上锁了,还是阻止不了新插入的记录

如何解决幻读

产生的幻读的原因是:行锁只能锁住行

为了解决幻读问题,InnoDB引入新的锁:间隙锁(Gap Lock)

间隙锁,锁的就是两个值之间的空隙,比如在表t,初始化插入了6个记录,就产生了7个间隙:

执行:

select * from t where d = 5 for update

6个记录加上了行锁,同时加上了7个间隙锁。

间隙锁与行锁有点不一样

行锁可以分为读锁与写锁

与行锁有冲突关系的是另外一个行锁。

间隙锁不一样,间隙锁之间不存在冲突关系。

与间隙锁存在冲突关系的,是"向间隙中插入一个记录"这个操作。

举例:

由于表t中并没有c=7这个记录,所以session A加的是间隙锁(5,10)。而session B也是在这个间隙加的间隙锁,它们的目标都是保护这个间隙,不允许插入值,所以两者不冲突。

next-key lock

间隙锁与行锁合称next-key lock,每个lock都是前开后闭区间。间隙锁是开区间。

如上面我们插入数据,使用:

select * from t for update

形成了7个next-key lock,分别是:

(-∞,0]、(0,5]、(5,10]、(10,15]、(15,20]、(20, 25]、(25, +supremum]

supremum是一个不存在的最大值。

next-key lock 的引入解决了幻读问题,但是也带来了新的问题。

如,现在有这样一个业务逻辑:

任意锁住一行,如果这一行不存在的话就插入,如果存在这一行就更新它的数据。

begin;
select * from t where id = N for update;
--如果行不存在
insert into t values(N,N,N);
--如果行存在
update t set d = N set id = N;commit;

现在出现这个现象:这个逻辑一旦有并发,就会碰到死锁。

死锁的产生:两个间隙锁不冲突,相互等待行锁

执行流程:

1、session A执行select…for update语句,由于id=9这一行不存在,因此会加上间隙锁(5,10)

2、session B执行select…for update语句,同样会加上间隙锁(5,10)

3、session B插入(9,9,9),被session A的间隙锁锁住,进入等待

4、session A擦汗如·插入(9,9,9),被session B的间隙锁锁住。

InnoDB死锁检测发现了这对死锁关系,然后报错返回了。

所以说间隙锁的引入可能会导致相同的语句锁住更大的范围,从而影响并发度。

间隙锁是在可重复读隔离级别下才会生效的。所以,你如果把隔离级别设置为读提交的话,就没有间隙锁了。 但同时,你要解决可能出现的数据和日志不一致问题,需要把 binlog 格式设置为 row。

《MySQL——幻读与next-key lock与间隙锁带来的死锁》相关推荐

  1. ComeFuture英伽学院——2020年 全国大学生英语竞赛【C类初赛真题解析】(持续更新)

    视频:ComeFuture英伽学院--2019年 全国大学生英语竞赛[C类初赛真题解析]大小作文--详细解析 课件:[课件]2019年大学生英语竞赛C类初赛.pdf 视频:2020年全国大学生英语竞赛 ...

  2. ComeFuture英伽学院——2019年 全国大学生英语竞赛【C类初赛真题解析】大小作文——详细解析

    视频:ComeFuture英伽学院--2019年 全国大学生英语竞赛[C类初赛真题解析]大小作文--详细解析 课件:[课件]2019年大学生英语竞赛C类初赛.pdf 视频:2020年全国大学生英语竞赛 ...

  3. 信息学奥赛真题解析(玩具谜题)

    玩具谜题(2016年信息学奥赛提高组真题) 题目描述 小南有一套可爱的玩具小人, 它们各有不同的职业.有一天, 这些玩具小人把小南的眼镜藏了起来.小南发现玩具小人们围成了一个圈,它们有的面朝圈内,有的 ...

  4. 信息学奥赛之初赛 第1轮 讲解(01-08课)

    信息学奥赛之初赛讲解 01 计算机概述 系统基本结构 信息学奥赛之初赛讲解 01 计算机概述 系统基本结构_哔哩哔哩_bilibili 信息学奥赛之初赛讲解 02 软件系统 计算机语言 进制转换 信息 ...

  5. 信息学奥赛一本通习题答案(五)

    最近在给小学生做C++的入门培训,用的教程是信息学奥赛一本通,刷题网址 http://ybt.ssoier.cn:8088/index.php 现将部分习题的答案放在博客上,希望能给其他有需要的人带来 ...

  6. 信息学奥赛一本通习题答案(三)

    最近在给小学生做C++的入门培训,用的教程是信息学奥赛一本通,刷题网址 http://ybt.ssoier.cn:8088/index.php 现将部分习题的答案放在博客上,希望能给其他有需要的人带来 ...

  7. 信息学奥赛一本通 提高篇 第六部分 数学基础 相关的真题

    第1章   快速幂 1875:[13NOIP提高组]转圈游戏 信息学奥赛一本通(C++版)在线评测系统 第2 章  素数 第 3 章  约数 第 4 章  同余问题 第 5 章  矩阵乘法 第 6 章 ...

  8. 信息学奥赛一本通题目代码(非题库)

    为了完善自己学c++,很多人都去读相关文献,就比如<信息学奥赛一本通>,可又对题目无从下手,从今天开始,我将把书上的题目一 一的解析下来,可以做参考,如果有错,可以告诉我,将在下次解析里重 ...

  9. 信息学奥赛一本通(C++版) 刷题 记录

    总目录详见:https://blog.csdn.net/mrcrack/article/details/86501716 信息学奥赛一本通(C++版) 刷题 记录 http://ybt.ssoier. ...

  10. 最近公共祖先三种算法详解 + 模板题 建议新手收藏 例题: 信息学奥赛一本通 祖孙询问 距离

    首先什么是最近公共祖先?? 如图:红色节点的祖先为红色的1, 2, 3. 绿色节点的祖先为绿色的1, 2, 3, 4. 他们的最近公共祖先即他们最先相交的地方,如在上图中黄色的点就是他们的最近公共祖先 ...

最新文章

  1. 无意中发现一位大佬的算法刷题pdf笔记
  2. Android7.0 Doze模式分析(一)Doze介绍 amp; DeviceIdleController
  3. oracle的脚本语言是什么意思,Oracle中的sql脚本语言中的循环语句介绍
  4. 索引(转载自百度百科)
  5. devops定义_在层中定义DevOps
  6. 第二章:在HTML中使用JavaScript
  7. 浏览器对象模型BOM、文档对象模型DOM
  8. 修改服务器linux的yum源为阿里源yum源
  9. 12.2.1 QTcpSocket类介绍
  10. Android常见面试题字节跳动、阿里、腾讯2019实习生Android岗部分面试题
  11. v2ex站长专访 - 100offer专访Livid:不仅仅是V站站长
  12. 关于系统分析师的考试感想
  13. 如何使用HTML5+CSS3绘制一个QQ 企鹅Logo
  14. iOS 应用内购买(In-App Purchase)之开发
  15. jdk1.7安装详细过程
  16. c++实现sqrt函数功能
  17. 收单外包机构为何会被强制取消备案
  18. 【抗干扰代码】AVR单片机自动复位由于电压不足导致ENC28J60网卡出现的故障
  19. 大数据 数据治理 | 微信交流群~
  20. Python实战案例:高血压项目详解(上)

热门文章

  1. 一次线上ctf的网络协议分析
  2. 多线程写mysql数据库_多线程读写mysql数据库
  3. java读取文件方法
  4. openocd安装与调试
  5. webpack联邦模块之remotes方法
  6. [leetcode-108,109] 将有序数组转换为二叉搜索树
  7. Web Magic 总体架构
  8. 04 linux用户群组和权限
  9. python之路-SQLAlchemy
  10. 如何在自己的代码中实现分享视频文件或者是图片文件到微信 QQ微博 新浪微博等!!!...