你需要知道的

之前我们介绍了排他锁,其实innodb下的记录锁(也叫行锁),间隙锁,next-key锁统统属于排他锁。

行锁

记录锁其实很好理解,对表中的记录加锁,叫做记录锁,简称行锁。

生活中的间隙锁

编程的思想源于生活,生活中的例子能帮助我们更好的理解一些编程中的思想。

生活中排队的场景,小明,小红,小花三个人依次站成一排,此时,如何让新来的小刚不能站在小红旁边,这时候只要将小红和她前面的小明之间的空隙封锁,将小红和她后面的小花之间的空隙封锁,那么小刚就不能站到小红的旁边。

这里的小红,小明,小花,小刚就是数据库的一条条记录。

他们之间的空隙也就是间隙,而封锁他们之间距离的锁,叫做间隙锁。

Mysql中的间隙锁

下表中(见图一),id为主键,number字段上有非唯一索引的二级索引,有什么方式可以让该表不能再插入number=5的记录?

图一

根据上面生活中的例子,我们自然而然可以想到,只要控制几个点,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=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);

间隙锁的目的是为了防止幻读,其主要通过两个方面实现这个目的:

(1)防止间隙内有新数据被插入

(2)防止已存在的数据,更新成间隙内的数据(例如防止numer=3的记录通过update变成number=5)

innodb自动使用间隙锁的条件:

(1)必须在RR级别下

(2)检索条件必须有索引(没有索引的话,mysql会全表扫描,那样会锁定整张表所有的记录,包括不存在的记录,此时其他事务不能修改不能删除不能添加)

接下来,通过实际操作观察下间隙锁的作用范围

图三 表结构

案例一:

````

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 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,无穷大)。

有人会问,为啥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:

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),如下图所示:

有人会问,为啥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:

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,无穷大),如下图所示:

session2中之所以有些阻塞,有些执行成功,其实就是因为插入的区域被锁定,从而阻塞。

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间隙锁相关推荐

  1. mysql 查看锁表日志_MYSQL 表锁情况查看

    查看锁表情况 mysql> show status like 'Table%'; +----------+--–+ | Variable_name | Value | +----------+- ...

  2. mysql行锁表怎么办_mysql - 表锁,行锁

    MyISAM存储引擎:开销小,加锁快,无死锁.锁定粒度大,并发度低,容易发生锁冲突.   不支持事务.            采用表锁 (操作时对操作的表上锁) 基本不用了 innoDB存储引擎:开销 ...

  3. mysql数据锁的类型_MySQL数据库锁类型

    锁概念: 当高并发访问同一个资源时,可能会导致数据不一致,需要一种机制将用户访问数据的顺序进行规范化,以保证数据库数据的一致性.锁就是其中的一种机制. 一个栗子 :以买火车票为例,火车票可面向广大消费 ...

  4. mysql 数据库表被锁住了_mysql数据库锁的产生原因及解决办法

    数据库和操作系统一样,是一个多用户使用的共享资源.当多个用户并发地存取数据 时,在数据库中就会产生多个事务同时存取同一数据的情况.若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性 ...

  5. mysql MDL锁如何解决_MySQL元数据锁MDL

    [TOC] > 除了我们经常熟知的共享锁和排他锁外,MySQL数据库还有一种锁叫元数据锁,主要为了保证元数据的一致性,用于处理不同线程操作同一数据对象的同步与互斥问题. # 一.元数据 所谓元数 ...

  6. mysql锁表查询_Mysql数据库锁情况下开启备份导致数据库无法访问处理分享

    [背景简介] MySQL是一种开放源代码的关系型数据库管理系统(RDBMS),因为其速度.可靠性和适应性而备受关注.大多数人都认为在不需要事务化处理的情况下,MySQL是管理内容最好的选择.mysql ...

  7. mysql 不锁表备份_Mysql不锁表备份之Xtrabackup的备份与恢复

    一.Xtrabackup介绍 MySQL冷备.热备.mysqldump都无法实现对数据库进行增量备份.如果数据量较大我们每天进行完整备份不仅耗时且影响性能.而Percona-Xtrabackup就是为 ...

  8. mysql悲观锁的应用_mysql悲观锁

    悲观锁与乐观锁是两种常见的资源并发锁设计思路,也是并发编程中一个很是基础的概念.mysql 悲观锁(Pessimistic Lock) 悲观锁的特色是先获取锁,再进行业务操做,即"悲观&qu ...

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

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

  10. mysql临键锁_详解 MySql InnoDB 中的三种行锁(记录锁、间隙锁与临键锁)

    详解 MySql InnoDB 中的三种行锁(记录锁.间隙锁与临键锁) 前言 InnoDB 通过 MVCC 和 NEXT-KEY Locks,解决了在可重复读的事务隔离级别下出现幻读的问题.MVCC  ...

最新文章

  1. Hashtable 中的键值修改问题
  2. matplotlib坐标轴调整
  3. IDOC实例, Inbound IDOC
  4. 使用Xamarin实现跨平台移动应用开发
  5. 最短路径(弗洛伊德算法)
  6. Daimler CRM中间件 inbound 调试
  7. 关于计算机网络与应用的相关片,网络技术与应用作业.doc
  8. 什么是Web Server
  9. 电切镜行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  10. 控制理论与控制工程_控制理论与控制工程专业介绍_研究方向_就业前景分析
  11. recurdyn和matlab联合仿真,基于RecurDyn与Simulink的液压破碎锤联合仿真与试验分析
  12. Nopi的学习笔记(C#篇)
  13. 联想笔记本连不上手机热点_笔记本电脑连接不上手机热点该怎么解决?
  14. Redhat克隆及其配置
  15. Java汉字转拼音(简繁体转换)库之JPinYin
  16. 基于单片机水温自动控制系统设计-毕设课设资料
  17. 分形蕨( fractal fern)
  18. MySQL 5.6.22绿色版安装
  19. 密码学技术如何选型?终探量子计算通信的安全模型|第6论
  20. 中秋晴朗夜,我们与星月相见

热门文章

  1. 浅析双11背后的电商IT基础架构
  2. 虚短虚断以及部分运放电路
  3. 华硕服务器主板那个系列好,华硕主板型号性价比排行 华硕主板那个性价最好用...
  4. STM32MP157 u-boot2021.10移植
  5. 计算机操作系统教程徐甲同pdf,《操作系统实践教程》.pdf
  6. 【Python爬虫+js逆向】使用Python爬取腾讯漫画的逆向分析(典型签名验证反爬虫的解决方案)——以腾讯动漫《一人之下》第一话为例
  7. 获取代理IP的三种途径
  8. MPush安装部署应用
  9. wgs84坐标系拾取工具_百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换的工具...
  10. matlab的火山图,ggplot绘制火山图