间隙锁与Next-Key锁以及防止幻读
概述
InnoDB中行锁一共有3种,分别是:记录锁(Record lock)
、间隙锁
和Next-Key锁
。
Record锁
是作用于单条行记录,而间隙锁
和Next-Key锁
是一个范围锁,可锁定某个范围的行记录,它们是很相近的概念,可以说后者包含了前者,它们可以用来解决RR隔离级别
下的幻读问题。
注意:如果检索条件不是索引的话会全表扫描,则是表锁,不是行锁
间隙锁
首先间隙锁
是行锁,运行在RR隔离级别
下。其次,它锁住的是一个范围,但不包括记录本身。
触发语句
在RR隔离级别
下的一个非表扫描的条件检索语句加上共享锁
或排它锁
就触发了间隙锁
(其实是触发的是Next-Key锁
,后面解释)。
1 | mysql> select * from users where age = 20 for update; |
上面实例中的age字段是一个索引字段,确保检索操作走的是索引。
锁定范围
当检索条件是
=
时,锁定结果记录与上行和下行的间隙。当检索条件是个范围时,就给这个范围锁定。
假设有张users表,ID为自增主键,age为索引字段。全部的数据如表单1。
表单1
age | ID |
---|---|
10 | 100 |
23 | 101 |
14 | 102 |
20 | 107 |
20 | 108 |
26 | 120 |
16 | 123 |
我们将要演示语句走的是age辅助索引,又因为这个索引使用B树
数据结构,索引中的排序是从小到大的或从大到小的,不是表单1看的那样,而是表单2那样。
表单2
age |
---|
10 |
14 |
16 |
20 |
20 |
23 |
26 |
等于条件检索
1 | mysql> select * from users where age = 20 for update; |
观看表单2,我们可以看到”20”与上行”10”的间隙是(16, 20),”20”与下行”23”的间隙是(20, 23),这2个区间将会被锁定。也就是你想插入一条age的值在这个区间的新记录,或者修改某已经存在的行的age值为这2个区间时,都将会被阻塞。
范围条件检索
1 | mysql> select * from users where age > 23 and age < 26 for update; |
如语句限制,age值范围为(23, 26)的记录的插入或修改都会被阻塞。
Next-Key锁
当启用触发加锁语句后,Next-Key锁
是InnoDB默认加锁方式。
它是间隙锁
和记录锁
的结合,它锁住的是一个范围,并且包括记录本身。
于是上面的”等于条件检索”演示的锁定范围就变成(16, 23)。
防止幻读
幻读:
幻读指的是一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行。
如何防止幻读?就是不允许其它事务插入或修改某些数据。
例如,某事务要获取年龄在(23, 26)之间的用户,为了防止幻读,也就是不允许其它事务插入年龄也在(23, 26)之间的用户,给查询语句加锁Next-Key锁
就解决问题了。
1 | mysql> select * from users where age > 23 and age < 26 for update; |
本文标题:间隙锁与Next-Key锁以及防止幻读
文章作者:biteyu
发布时间:2016-08-12
原始链接:https://www.biteyu.cn/a/532170.html
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN 许可协议。转载请注明出处!