Mysql加锁过程详解(9)-innodb下的记录锁,间隙锁,next-key锁
2017-11-12 13:30
573 查看
之前我们介绍了排他锁,其实innodb下的记录锁(也叫行锁),间隙锁,next-key锁统统属于排他锁。[b]行锁[/b]
记录锁其实很好理解,对表中的记录加锁,叫做记录锁,简称行锁。[b]生活中的间隙锁[/b]
编程的思想源于生活,生活中的例子能帮助我们更好的理解一些编程中的思想。
生活中排队的场景,小明,小红,小花三个人依次站成一排,此时,如何让新来的小刚不能站在小红旁边,这时候只要将小红和她前面的小明之间的空隙封锁,将小红和她后面的小花之间的空隙封锁,那么小刚就不能站到小红的旁边。
这里的小红,小明,小花,小刚就是数据库的一条条记录。
他们之间的空隙也就是间隙,而封锁他们之间距离的锁,叫做间隙锁。[b]Mysql中的间隙锁[/b]
下表中(见图一),id为主键,number字段上有非唯一索引的二级索引,有什么方式可以让该表不能再插入number=5的记录?
答案是用间隙锁,在RR级别下,mysql通过间隙锁可以实现锁定number=5之前的间隙,number=5记录之间的间隙,number=5之后的间隙,从而使的新的记录无法被插入进来。[b]间隙是怎么划分的?[/b]注:为了方面理解,我们规定(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)之间有间隙的,[b]间隙锁锁定的区域[/b]
根据检索条件向左寻找最靠近检索条件的记录值A,作为左区间,向右寻找最靠近检索条件的记录值B作为右区间,即锁定的间隙为(A,B)。
图一中,wherenumber=5的话,那么间隙锁的区间范围为(4,11);[b]间隙锁的目的是为了防止幻读,其主要通过两个方面实现这个目的:[/b]
(1)防止间隙内有新数据被插入
(2)防止已存在的数据,更新成间隙内的数据(例如防止numer=3的记录通过update变成number=5)[b]innodb自动使用间隙锁的条件:[/b]
(1)必须在RR级别下
(2)检索条件必须有索引(没有索引的话,mysql会全表扫描,那样会锁定整张表所有的记录,包括不存在的记录,此时其他事务不能修改不能删除不能添加)[b]接下来,通过实际操作观察下间隙锁的作用范围[/b]
```` session1: starttransaction; select*fromnewswherenumber=4forupdate; session2: starttransaction; insertintonewsvalue(2,4);#(阻塞) insertintonewsvalue(2,2);#(阻塞) insertintonewsvalue(4,4);#(阻塞) insertintonewsvalue(4,5);#(阻塞) insertintonewsvalue(7,5);#(执行成功) insertintonewsvalue(9,5);#(执行成功) insertintonewsvalue(11,5);#(执行成功) ````
检索条件number=4,向左取得最靠近的值2作为左区间,向右取得最靠近的5作为右区间,因此,session1的间隙锁的范围(2,4),(4,5),如下图所示:
````
session1:
starttransaction;
select*fromnewswherenumber=13forupdate;session2:
starttransaction;
insertintonewsvalue(11,5);#(执行成功)
insertintonewsvalue(12,11);#(执行成功)
insertintonewsvalue(14,11);#(阻塞)
insertintonewsvalue(15,12);#(阻塞)
updatenewssetid=14wherenumber=11;#(阻塞)
updatenewssetid=11wherenumber=11;#(执行成功)
````
检索条件number=13,向左取得最靠近的值11作为左区间,向右由于没有记录因此取得无穷大作为右区间,因此,session1的间隙锁的范围(11,无穷大),如下图所示:
````
session1:
starttransaction;
select*fromnewswherenumber=5forupdate;session2:
starttransaction;
insertintonewsvalue(4,4);#(阻塞)
insertintonewsvalue(4,5);#(阻塞)
insertintonewsvalue(5,5);#(阻塞)
insertintonewsvalue(7,11);#(阻塞)
insertintonewsvalue(9,12);#(执行成功)
insertintonewsvalue(12,11);#(阻塞)
updatenewssetnumber=5whereid=1;#(阻塞)
updatenewssetid=11wherenumber=11;#(阻塞)
updatenewssetid=2wherenumber=4;#(执行成功)
updatenewssetid=4wherenumber=4;#(阻塞)
````
检索条件number=5,向左取得最靠近的值4作为左区间,向右取得11为右区间,因此,session1的间隙锁的范围(4,5),(5,11),如下图所示:
number=5的记录的前面,后面包括中间都被封锁了,你这个updatenewssetnumber=5whereid=1根本没法执行,因为innodb已经把你可以存放的位置都锁定了,因为只能等待。同理,updatenewssetid=11wherenumber=11由于记录(id=10,number=5)与记录(id=13,number=11)中间的间隙被封锁了,你这句sql也没法执行,必须等待,因为存放的位置被封锁了。[b]案例四:[/b]
session1:
starttransaction;
select*fromnewswherenumber>4forupdate;session2:
starttransaction;
updatenewssetid=2wherenumber=4;#(执行成功)
updatenewssetid=4wherenumber=4;#(阻塞)
updatenewssetid=5wherenumber=5;#(阻塞)
insertintonewsvalue(2,3);#(执行成功)
insertintonewsvalue(null,13);#(阻塞)
检索条件number>4,向左取得最靠近的值4作为左区间,向右取无穷大,因此,session1的间隙锁的范围(4,无穷大),如下图所示:
next-key锁其实包含了记录锁和间隙锁,即锁定一个范围,并且锁定记录本身,InnoDB默认加锁方式是next-key锁。
上面的案例一session1中的sql是:select*fromnewswherenumber=4forupdate;
next-key锁锁定的范围为间隙锁+记录锁,即区间(2,4),(4,5)加间隙锁,同时number=4的记录加记录锁。
from:
相关文章推荐
- 推荐:mysql锁 innodb下的记录锁,间隙锁,next-key锁
- Mysql加锁过程详解(8)-理解innodb的锁(record,gap,Next-Key lock)
- Mysql加锁过程详解(8)-理解innodb的锁(record,gap,Next-Key lock)
- Mysql innodb 间隙锁: 记录不存在也会加间隙锁
- innodb的记录锁、gap锁、next-key锁
- mysql存储引擎InnoDB插入数据的过程详解
- mysql存储过程基础之遍历多表记录后插入第三方表中详解
- innodb的记录锁、gap锁、next-key锁
- Mysql加锁过程详解(5)-innodb 多版本并发控制原理详解
- innodb下的记录锁,间隙锁,next-key锁
- Mysql加锁过程详解(5)-innodb 多版本并发控制原理详解
- MySQL存储过程详解 mysql 存储过程
- mysql-5.7 innodb 的并行任务调度详解
- MySQL的InnoDB索引原理详解
- 资深架构师Sum的故事:(Mysql)InnoDB下,存储过程中事务的处理
- QT 5 配置MySQL 过程记录
- MySQL存储过程详解 mysql 存储过程
- MySQL中InnoDB的间隙锁问题
- MySQL配置主从同步过程记录
- 用PHP和MYSQL建立计数器过程详解