gap锁(间隙锁)的各类验证

6 篇文章 0 订阅
4 篇文章 0 订阅

gap锁(间隙锁)

间隙锁实质上是对索引前后的间隙上锁,不对索引本身上锁。
根据检索条件向左寻找最靠近检索条件的记录值A,作为左区间,向右寻找最靠近检索条件的记录值B作为右区间,即锁定的间隙为(A,B)。
间隙锁的目的是为了防止幻读,其主要通过两个方面实现这个目的:
(1)防止间隙内有新数据被插入。
(2)防止已存在的数据,更新成间隙内的数

我们这里会将不同情况下间隙锁的展示,字母,以及数字

首先,我们需要明白几个条件
一、这个是针对事务下的
二、这个是需要索引支持
三、索引是非唯一的,也就是index

数字

创建表

create table data(list1 int(5),list2 int(5),index(list1));

插入数据

insert into data(list1,list2) values(3,104);
insert into data(list1,list2) values(6,104);
insert into data(list1,list2) values(8,104);

mysql> select * from data;
+-------+-------+
| list1 | list2 |
+-------+-------+
|     3 |   104 |
|     6 |   104 |
|     8 |   104 |
+-------+-------+
5 rows in set (0.00 sec)

好了,我们来解释并验证一下

一、数字之间有顺序

所谓间隙锁,也就是将你指定的,且带有索引的那一行以及旁边的两行锁起来,我们来想一想为什么这样就不会出现幻数了,比如说,我现在想要改6这行的104,首先,我们查看6

mysql> select * from data where list1=6;
+-------+-------+
| list1 | list2 |
+-------+-------+
|     6 |   104 |
+-------+-------+
1 row in set (0.00 sec)

所谓出现幻数就是,我们开启事务之后,我们查这个6,是只有一行,但是,突然间有个傻逼又加了一行,事务查询就变成

mysql> select * from data where list1=6;
+-------+-------+
| list1 | list2 |
+-------+-------+
|     6 |   104 |
|     6 |   105 |
+-------+-------+
1 row in set (0.00 sec)

我们自然知道是多加了一行,但是事务处理的时候它自己整不明白啊,这个时候就会出现事务要修改的时候,发现有两行数据,明明刚刚才只有一条而已
这时候就体现了间隙锁的威力了
我们把事务开启

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update data set list2=105 where list1=6;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

另一个会话进行插入一个6的数据

mysql> insert into data(list1,list2) values(6,202);

可以看到,这玩意卡住了,它正在等待事务的结束,我们继续插入周边的数据

mysql> insert into data(list1,list2) values(7,202);

依旧是卡住的

mysql> insert into data(list1,list2) values(5,202);

我们插个8进去,成功了

mysql> insert into data(list1,list2) values(8,202);
Query OK, 1 row affected (0.00 sec)

插个3进去,卡住了

mysql> insert into data(list1,list2) values(3,202);

这就是有趣的地方了,也是比较难理解的地方,我们所谓索引,并不是我们看到的那么简单,我们使用select看到的顺序是3 6 8,也就是说明3,4,6,7都在这个集合里面,与这几个相关的都是无法正常插入的,为什么8可以呢,我们想一想,插入数据是插在下面的,那是不是就不是在这个缝隙里面了

有些机灵鬼就要说了,你这数据是并排起来的,那如果乱来呢,我们依旧来验证一下,我又创建了data1

二、数字之间没有顺序

mysql> select * from data1;
+-------+-------+
| list1 | list2 |
+-------+-------+
|     6 |   104 |
|     3 |   104 |
|     8 |   104 |
+-------+-------+
3 rows in set (0.00 sec)
mysql> insert into data(list1,list2) values(3,202);
^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted
mysql> insert into data(list1,list2) values(8,202);
Query OK, 1 row affected (0.00 sec)
mysql> insert into data(list1,list2) values(5,202);
^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted

你会发现,结果会和之前一样,也就是说,固定是根据你select出来,你看到的数字左右两边的集合,不管你的顺序是什么,索引会帮你排号它们

欸,那边界呢

三、边界数字

mysql> update data1 set list2=106 where list1=8;
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2  Changed: 2  Warnings: 0

我们这边使用边界数8
插入一些数字

mysql> insert into data1(list1,list2) values(1,202);
Query OK, 1 row affected (0.00 sec)
mysql> insert into data1(list1,list2) values(7,202);
^C^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted
mysql> insert into data1(list1,list2) values(100,202);
^C^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted

发现只有小于6的可以插入

我们可以整理一下

mysql> select * from data;
+-------+-------+
| list1 | list2 |
+-------+-------+
|     3 |   104 |
|     6 |   104 |
|     8 |   104 |
+-------+-------+

一、
我们选择6的时候,6作为中间数被
锁定范围为[3,6]U[6,8)
即便顺序不一样也是这样的
二、
我们选择边界数的时候,比如8
锁定范围为[6,8]U[8,∞)
我们选择边界数3的时候,
锁定范围为(∞,3]U[3,6)

字母

不是我挑了好讲的数字来说,而是两者是基本上一样的
字母也有字母的范围,[Aa-Zz]为什么这么写,MySQL是大小写不敏感

mysql> select * from data3;
+-------+-------+
| list1 | list2 |
+-------+-------+
| a     | asad  |
| c     | asad  |
| F     | asad  |
+-------+-------+
3 rows in set (0.00 sec)

新表,有大小写
开始验证

一、单字母验证

创建事务

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update data3 set list2='dasd' where list1='c';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

插入验证

mysql> insert into data3(list1,list2) values('d','asd');
^C^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted
mysql> insert into data3(list1,list2) values('D','asd');
^C^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted
mysql> insert into data3(list1,list2) values('E','asd');
^C^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted
mysql> insert into data3(list1,list2) values('F','asd');
Query OK, 1 row affected (0.00 sec)

看到了吗,只有F能够插进去
这还需要解释吗?跟上面数字的8有什么不同?也就是有大小写而已,大小写不敏感,因此是一样的

我们现在需要想一下,在数字里面8和88是有对比的,因为88大过8,但是F和FF是不一样的,这两个可没有办法比较呀ascll码也不能这样加吧

二、多字母验证

事务开启

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update data3 set list2='dasd' where list1='c';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 0

插入验证

mysql> insert into data3(list1,list2) values('EE','asd');
^C^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted
mysql> insert into data3(list1,list2) values('aa','asd');
^C^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted
mysql> insert into data3(list1,list2) values('Avdf','asd');
^C^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted
mysql> insert into data3(list1,list2) values('fsdd','asd');
Query OK, 1 row affected (0.00 sec)

看到了吗,是不准的,也就是说明,字母的验证是根据首字母的

好了,GAP间隙锁验证结束

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值