innodb下的记录锁(也叫行锁),间隙锁,next-key锁统统属于排他锁。行锁,即记录锁,其实很好理解,对表中的记录加锁,叫做记录锁,简称行锁。就不多做介绍,主要介绍间隙锁,next-key锁。

间隙锁

间隙锁,顾名思义就是存在间隙,在间隙之间上锁保证在间隙间不可以进行操作。举一个生活中比较好理解得例子,A,B,C依次排成一排,为了让新来的D不能插在B的旁边,只要将B和A之间的空隙封锁,将B和C之间的空隙封锁,那么D就不能插在B的旁边了。他们之间的空隙也就是间隙,而封锁他们之间距离的锁,叫做间隙锁。这里映射到数据库层面,A,B,C,D就是数据库的一条条记录。

Mysql中的间隙锁

假设数据库中某个表存在以下数据,其中id为主键,number字段上有非唯一索引的二级索引,有什么方式可以让该表不能再插入number=5的记录呢?

id(主键) number(二级索引)
1 2
3 4
6 5
8 5
10 5
13 11

由之前的概念可以想到,只要控制number=5之前不能插入记录,number=5现有的记录之间不能再插入新的记录,number=5之后不能插入新的记录,那么新的number=5的记录将不能被插入进来。那么,mysql是如何控制number=5之前,之中,之后不能有新的记录插入呢(防止幻读)?答案是用间隙锁。
在RR级别下,mysql通过间隙锁可以实现锁定number=5之前的间隙,number=5记录之间的间隙,number=5之后的间隙,从而使的新的记录无法被插入进来。间隙锁要通过两个方面实现防止幻读:

  • 防止间隙内有新数据被插入
  • 防止已存在的数据,更新成间隙内的数据
    接下来带大家来理解一下具体的含义。

间隙锁的间隙划分

为了方便理解,我们规定(id=A,number=B)代表一条字段id=A,字段number=B的记录,(C,D)代表一个区间,代表C-D这个区间范围。所以在上图中,根据number列,可以分为几个区间:(无穷小,2),(2,4),(4,5),(5,5),(5,11),(11,无穷大)。只要这些区间对应的两个临界记录中间可以插入记录,就认为区间对应的记录之间有间隙。例如区间(2,4)分别对应的临界记录是(id=1,number=2),(id=3,number=4),这两条记录中间可以插入(id=2,number=3)等记录,那么就认为(id=1,number=2)与(id=3,number=4)之间存在间隙。同理(id=6,number=5)与(id=8,number=5)之间可以插入记录(id=7,number=5),因此(id=6,number=5)与(id=8,number=5)之间有间隙的。

间隙锁的锁定区域

根据检索条件向左寻找最靠近检索条件的记录值A,作为左区间,向右寻找最靠近检索条件的记录值B作为右区间,即锁定的间隙为(A,B)。如上图中,where number=5的话,那么间隙锁的区间范围为(4,11)。

间隙锁的实际操作

接下来我们通过几个具体的例子来观察下间隙锁的作用范围。

实际操作一

有如下两个事务操作,我们分析一下当session 1执行的时候,session 2中的insert操作是否可以执行成功。

session 1:
start  transaction ;
select  * from news where number=4 for update ;session 2:
start  transaction ;
insert into news value(2,4);
insert into news value(2,2);
insert into news value(4,4);
insert into news value(4,5);
insert into news value(7,5);
insert into news value(9,5);
insert into news value(11,5);

检索条件number=4,向左取得最靠近的值2作为左区间,向右取得最靠近的5作为右区间,因此,session 1的间隙锁的范围(2,4),(4,5),如下图所示:

间隙锁锁定的区间为(2,4),(4,5),即记录(id=1,number=2)和记录(id=3,number=4)之间间隙会被锁定,记录(id=3,number=4)和记录(id=6,number=5)之间间隙被锁定。因此记录(id=2,number=4),(id=2,number=2),(id=4,number=4),(id=4,number=5)正好处在(id=3,number=4)和(id=6,number=5)之间,所以插入不了,需要等待锁的释放,而记录(id=7,number=5),(id=9,number=5),(id=11,number=5)不在上述锁定的范围内,因此都会插入成功。

session 2:
start  transaction ;
insert into news value(2,4);#(阻塞)
insert into news value(2,2);#(阻塞)
insert into news value(4,4);#(阻塞)
insert into news value(4,5);#(阻塞)
insert into news value(7,5);#(执行成功)
insert into news value(9,5);#(执行成功)
insert into news value(11,5);#(执行成功)

实际操作二

有如下两个事务操作,我们同样来分析一下当session 1执行的时候,session 2中的insert操作是否可以执行成功。

session 1:
start  transaction ;
select  * from news where number=13 for update ;session 2:
start  transaction ;
insert into news value(11,5);
insert into news value(12,11);
insert into news value(14,11);
insert into news value(15,12);
update news set id=14 where number=11;
update news set id=11 where number=11;

检索条件number=13,向左取得最靠近的值11作为左区间,向右由于没有记录因此取得无穷大作为右区间,因此,session 1的间隙锁的范围(11,无穷大),如下图所示:

此表中没有number=13的记录的,innodb依然会为该记录左右两侧加间隙锁,间隙锁的范围(11,无穷大)。因此记录(id=11,number=5),(id=12,number=11),(id=11,number=11),处在(id=13,number=11)之前,所以会插入成功,而记录(id=14,number=11),(id=15,number=12),(id=14,number=11)在上述锁定的范围内,因此操作阻塞,需要等待锁的释放。

session 2:
start  transaction ;
insert into news value(11,5);#(执行成功)
insert into news value(12,11);#(执行成功)
insert into news value(14,11);#(阻塞)
insert into news value(15,12);#(阻塞)
update news set id=14 where number=11;#(阻塞)
update news set id=11 where number=11;#(执行成功)

可能有人还是不太明白,为啥update news set id=14 where number=11会阻塞,但是update news set id=11 where number=11却执行成功呢?间隙锁采用在指定记录的前面和后面以及中间的间隙上加间隙锁的方式避免数据被插入,此图间隙锁锁定的区域是(11,无穷大),也就是记录(id=13,number=11)之后不能再插入记录,update news set id=14 where number=11这条语句如果执行的话,将会被插入到(id=13,number=11)的后面,也就是在区间(11,无穷大)之间,由于该区间被间隙锁锁定,所以只能阻塞等待,而update news set id=11 where number=11执行后是会被插入到(id=13,number=11)的记录前面,也就不在(11,无穷大)的范围内,所以无需等待,执行成功。

实际操作三

有如下两个事务操作,我们同样来分析一下当session 1执行的时候,session 2中的insert操作是否可以执行成功。

session 1:
start  transaction ;
select  * from news where number=5 for update;session 2:
start  transaction ;
insert into news value(4,4);
insert into news value(4,5);
insert into news value(5,5);
insert into news value(7,11);
insert into news value(9,12);
insert into news value(12,11);
update news set number=5 where id=1;
update news set id=11 where number=11;
update news set id=2 where number=4 ;
update news set id=4 where number=4 ;

检索条件number=5,向左取得最靠近的值4作为左区间,向右取得11为右区间,因此,session 1的间隙锁的范围(4,5),(5,11),如下图所示:

依据之前的分析方法,我想大家很快就可以得到一下的结论:

session 2:
start  transaction ;
insert into news value(4,4);#(阻塞)
insert into news value(4,5);#(阻塞)
insert into news value(5,5);#(阻塞)
insert into news value(7,11);#(阻塞)
insert into news value(9,12);#(执行成功)
insert into news value(12,11);#(阻塞)
update news set number=5 where id=1;#(阻塞)
update news set id=11 where number=11;#(阻塞)
update news set id=2 where number=4 ;#(执行成功)
update news set id=4 where number=4 ;#(阻塞)

有人会问,为啥insert into news value(9,12)会执行成功?间隙锁采用在指定记录的前面和后面以及中间的间隙上加间隙锁的方式避免数据被插入,(id=9,number=12)很明显在记录(13,11)的后面,因此不再锁定的间隙范围内。而为啥update news set number=5 where id=1会阻塞?number=5的记录的前面,后面包括中间都被封锁了,你这个update news set number=5 where id=1根本没法执行,因为innodb已经把你可以存放的位置都锁定了,因为只能等待。同理,update news set id=11 where number=11由于记录(id=10,number=5)与记录(id=13,number=11)中间的间隙被封锁了,你这句sql也没法执行,必须等待,因为存放的位置被封锁了。

实际操作三

有如下两个事务操作,我们同样来分析一下当session 1执行的时候,session 2中的insert操作是否可以执行成功。

session 1:
start  transaction;
select * from news where number>4 for update;session 2:
start  transaction;
update news set id=2 where number=4 ;
update news set id=4 where number=4 ;
update news set id=5 where number=5 ;
insert into news value(2,3);
insert into news value(null,13);

检索条件number>4,向左取得最靠近的值4作为左区间,向右取无穷大,因此,session 1的间隙锁的范围(4,无穷大),如下图所示:

同样依据之前的分析方式,也很容易得出以下的结论:

session 2:
start  transaction;
update news set id=2 where number=4 ;#(执行成功)
update news set id=4 where number=4 ;#(阻塞)
update news set id=5 where number=5 ;#(阻塞)
insert into news value(2,3);#(执行成功)
insert into news value(null,13);#(阻塞)

next-key锁

next-key锁其实包含了记录锁和间隙锁,即锁定一个范围,并且锁定记录本身,InnoDB默认加锁方式是next-key 锁。例如上面的实际操作一中的session 1的sql:

select * from news where number=4 for update ;

next-key锁锁定的范围为间隙锁+记录锁,即在区间(2,4),(4,5)加间隙锁,同时number=4的记录加记录锁。比较简单,就不做过多叙述。

猜你感兴趣
MYSQL专题-绝对实用的MYSQL优化总结
MYSQL专题-MySQL事务实现原理
MYSQL专题-MVCC多版本并发控制
MYSQL专题-MySQL三大日志binlog、redo log和undo log

更多文章请点击:更多…

参考文章:
https://www.jianshu.com/p/bf862c37c4c9

谈谈InnoDB下的记录锁,间隙锁,next-key锁相关推荐

  1. mysql 插入加锁_Mysql加锁过程详解(9)-innodb下的记录锁,间隙锁,next-key锁

    你需要知道的 之前我们介绍了排他锁,其实innodb下的记录锁(也叫行锁),间隙锁,next-key锁统统属于排他锁. 行锁 记录锁其实很好理解,对表中的记录加锁,叫做记录锁,简称行锁. 生活中的间隙 ...

  2. 推荐:mysql锁 innodb下的记录锁,间隙锁,next-key锁

    你需要知道的 之前我们介绍了排他锁,其实innodb下的记录锁(也叫行锁),间隙锁,next-key锁统统属于排他锁. 行锁 记录锁其实很好理解,对表中的记录加锁,叫做记录锁,简称行锁. 生活中的间隙 ...

  3. mysql事务基础+基于innodb的行锁+间隙锁+如何锁定行

    [0]README outlines are as follows : 行锁: 事务: 隔离级别: 行锁变表锁: 间隙锁: 如何锁定一行: 行锁总结: [1]行锁+事务+存储引擎基础 1.行锁: 偏向 ...

  4. MySQL高级 - 锁 - InnoDB行锁 - 间隙锁危害

    隙锁危害 当我们用范围条件,而不是使用相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据进行加锁: 对于键值在条件范围内但并不存在的记录,叫做 "间隙(GAP)&qu ...

  5. MySQL 与InnoDB 下的锁做朋友 (二)共享锁与排他锁

    前言 没有前言,我们直接看内容. 正文 共享锁(Shared Lock) 共享锁.S锁.读锁   ,都是他的叫法. 而我,喜欢叫他 共享读锁 . A shared (S) lock permits t ...

  6. mysql某个表被行锁了_MySQL中的锁(表锁、行锁)

    锁是计算机协调多个进程或纯线程并发访问某一资源的机制.在数据库中,除传统的计算资源(CPU.RAM.I/O)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所在有数 ...

  7. MySQL锁机制详解-表锁与行锁

    文章目录 1. 数据库锁理论 2. 锁的分类 2.1 按数据操作的类型分类 2.2 按数据操作的颗粒度分类 3. 表锁的应用 3.1 表锁相关命令 3.2 给表加表共享读锁 3.3 给表加表独占写锁 ...

  8. MySQL 锁全集(共享锁/排它锁、记录锁/间隙锁/临键锁)

    提升工作效率利器: ‎Mac App Store 上的"Whale - 任务管理.时间.卡片.高效率" 简介:锁是计算机协调多个进程或线程并发访问某一资源变得有序的机制. 一.锁分 ...

  9. 元数据解决分表不可 mysql_MySQL InnoDB技术内幕:内存管理、事务和锁

    前面有多篇文章介绍过MySQL InnoDB的相关知识,今天我们要更深入一些,看看它们的内部原理和机制是如何实现的. 一.内存管理 我们知道,MySQl是一个存储系统,数据最后都写在磁盘上.我们以前也 ...

最新文章

  1. 另存为里面没有jpg_选用打印捕捉功能将 SolidWorks 画面另存为JPG格式高清大图
  2. CentOS安装Java JDK
  3. druid连接池_SpringBoot整合JDBCTemplate及Druid连接池
  4. Android 动画(一)
  5. SAP CRM呼叫中心里confirm按钮的实现逻辑
  6. mfc 设置子窗口只打开一遍_MFC 判断子窗体是不是已经打开,避免重复创建
  7. android mapping.txt,Android根据mapping.txt还原混淆的代码
  8. 大数据_Flink_数据处理_案例WorldCount_批处理版---Flink工作笔记0008
  9. oracle dbv 离线,bbed和dbv检查数据文件结果不一致?
  10. 图像处理PILLOW的使用
  11. ADO.NET调用存储过程
  12. python时间序列如何拟合曲线_以“datetime”格式拟合时间序列的曲线?
  13. 20169217 2016-2017-2 《网络攻防实践》第四周学习总结
  14. Teamviewer远程连接提示疑似商业用途处理替代软件
  15. Docker配置阿里云加速器
  16. 关于CASS点自动连线方法
  17. VMware虚拟机丨VMware11虚拟机软件下载+安装教程
  18. 情人节程序员用HTML网页表白【七夕告白相册】 HTML5七夕情人节表白网页源码 HTML+CSS+JavaScript
  19. react的超详细讲解
  20. python 保障系统(一)

热门文章

  1. [hypervisor]-AArch64 (hypervisor)Virtualization学习笔记
  2. 功能强大的被动开源情报自动化侦察框架
  3. [保护模式]非PAE模式
  4. hook虚表监控虚表
  5. Objective-c 字符串的拼接
  6. 求1!+2!+3!+...+10!的值
  7. Mysql之外连接_OUTER JOIN
  8. MySQL解决root用户密码丢失问题
  9. 欧拉公式cos_谈谈欧拉公式与复指数信号
  10. 有了这个Java项目经历,面大厂稳了!