首页 技术 正文
技术 2022年11月22日
0 收藏 611 点赞 2,231 浏览 2578 个字

MySQL InnoDB支持三种行锁定方式:行锁(Record Lock):锁直接加在索引记录上面,锁住的是key。间隙锁(Gap Lock):锁定索引记录间隙,确保索引记录的间隙不变。间隙锁是针对事务隔离级别为可重复读或以上级别而已的。 Next-Key Lock :行锁和间隙锁组合起来就叫Next-Key Lock。默认情况下,InnoDB工作在可重复读隔离级别下,并且会以Next-Key Lock的方式对数据行进行加锁,这样可以有效防止幻读的发生。 Next-Key Lock是行锁和间隙锁的组合,当InnoDB扫描索引记录的时候,会首先对索引记录加上行锁(Record Lock),再对索引记录两边的间隙加上间隙锁(Gap Lock)。加上间隙锁之后,其他事务就不能在这个间隙修改或者插入记录。 

另外一个会话,的确插入不进去3这条记录

但begin后面后,紧跟的如果是select,则开启的是快照读(RR级别),如果后面再进行DML则会开启写锁,这前面可能会出现幻读的现象。

  Gap Lock在InnoDB的唯一作用就是防止其他事务的插入操作,以此防止幻读的发生。 行锁(Record Lock)行锁锁定的是索引记录,而不是行数据,也就是说锁定的是key。 间隙锁(Gap Lock)例如:create table test(id int,v1 int,v2 int,primary key(id),key `idx_v1`(`v1`))Engine=InnoDB DEFAULT CHARSET=UTF8;insert into test values(1,1,0);insert into test values(2,3,1);insert into test values(3,4,2);insert into test values(5,5,3);insert into test values(7,7,4);insert into test values(10,9,5);该表的记录如下:+—-+——+——+| id | v1 | v2 |+—-+——+——+| 1 | 1 | 0 || 2 | 3 | 1 || 3 | 4 | 2 || 5 | 5 | 3 || 7 | 7 | 4 || 10 | 9 | 5 | 间隙锁(Gap Lock)一般是针对非唯一索引而言的,test表中的v1(非唯一索引)字段值可以划分的区间为:(-∞,1)(1,3)(3,4)(4,5)(5,7)(7,9)(9, +∞)假如要更新v1=7的数据行,那么此时会在索引idx_v1对应的值,也就是v1的值上加间隙锁,锁定的区间是(5,7)和(7,9)。同时找到v1=7的数据行的主键索引和非唯一索引,对key加上锁。 后码锁(Next-Key Lock)记录锁和间隙锁的结合,对于InnoDB中,更新非唯一索引对应的记录(在这里来说是更新v1字段的值),会加上Next-Key Lock。如果更新记录为空,就不能加记录锁,只能加间隙锁。 以上情况的描述,皆是针对非唯一索引的场景。

为什么TRANSACTION 2的insert操作会被阻塞,产生等待呢?这是因为TRANSACTION 2插入的v1值为6在TRANSACTION 1的锁定区间(5,9)内。而TRANSACTION 1插入的v1值不在TRANSACTION 2的锁定区间(5,7)内,故可以成功插入。不仅仅insert操作, update操作也一样会被锁住,从而锁等待超时。 锁选择1)、如果更新条件没有走索引,例如执行”update from t1 set v2=0 where v2=5;” ,此时会进行全表扫描,扫表的时候,要阻止其他任何的更新操作,所以上升为表锁。2)、如果更新条件为索引字段,但是并非唯一索引(包括主键索引),例如执行“update from t1 set v2=0 where v1=9;” 那么此时更新会使用Next-Key Lock。使用Next-Key Lock的原因:a)、首先要保证在符合条件的记录上加上排他锁,会锁定当前非唯一索引和对应的主键索引的值;b)、还要保证锁定的区间不能插入新的数据。3)、如果更新条件为唯一索引,则使用Record Lock(记录锁)。由此可见,如果可以使用唯一索引的场景,则优先使用唯一索引InnoDB根据唯一索引,找到相应记录,将主键索引值和唯一索引值加上记录锁。但不使用Gap Lock(间隙锁) 间隙锁(Gap Lock)加后码锁的时候,并没有锁住间隙两端的记录(这里的两端分别是5,9和5,7),那么两端的记录是可以更新的,但是如果更新两端的记录会影响到间隙锁,那么操作会被挂起,等待间隙锁释放。

 环境=============================================================================

验证1============================================================================== 事务1start transaction;update test set v2=9 where v1=5;

事务2start transaction;update test set v1=3 where v1=4;如图片所示,事务不会被挂起再分析一下,事务1在非唯一索引上更新,有两个锁:行锁和间隙锁;行锁锁定的记录是v1为5的这一行,准确来说是在主键为5的key和v1索引为5的key上加了锁间隙锁 锁定了(4,5)、(5,7)这两个间隙,由于字段类型为 整数,也就剩下一个数字6可用 事务2中,对于where条件后面的v1字段,对于行锁,只要不为5,就不会与事务1的行锁发生冲突;对于gap lock,因为原来就没有6这一行,任何整数值都不会与事务1的gap lock发生冲突; 所以,事务2中会与事务1产生锁冲突的情景只剩下两种:更新v1为5的这一行索引字段值插入v1为6的数据下面再进行一次验证 验证2==============================================================================事务1同上事务2start transaction;update test set v1=6 where v1=1;事务2处于锁等待状态,结果与预期一致

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,082
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,556
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,406
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,179
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,815
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,898