mysql8 Record Locks ,Gap Locks, Next-Key Locks实验2 唯一索引和非唯一索引,无索引情况

mysql8 Record Locks ,Gap Locks, Next-Key Locks 实验1

mysql8 Record Locks ,Gap Locks, Next-Key Locks 实验3

上文讨论了 RR 隔离级别 主键索引的加锁情况,
本文接着讨论 RR 隔离级别下 二级唯一索引和普通二级索引 以及无索引时的加锁情况。

4.3 二级唯一索引等值查询

这次我们对 f1 字段操作,这是一个二级 唯一索引字段

4.3.1 锁定存在的值
-- 查询存在的值 11
START TRANSACTION;
SELECT PS_CURRENT_THREAD_ID() THREAD_ID ,t.* FROM locktest t WHERE t.f1=11  FOR UPDATE ;
-- 当前线程THREAD_ID=44
+-----------+----+----+----+----+
| THREAD_ID | id | f1 | f2 | f3 |
+-----------+----+----+----+----+
|        44 | 11 | 11 | 11 | 11 |
+-----------+----+----+----+----+
1 row in set (0.0 sec)

查询锁的信息,发现有3个锁,如下图所示:

在这里插入图片描述

【行号1】 是一个表级的意向锁

【行号2】 是一个加在 二级唯一索引 ui_f1上的 record 锁,锁类型为 X(排他),REC_NO__GAP 说明没有对间隙加锁

值得注意的是 LOCK_DATA为【11,11】 ,我们知道二级索引的record 组成为(key,主键),所以第一个11 是二级索引字段f1 的值,而第二个11 是主键的值

【行号3】 是一个主键索引上的 排他record 锁

4.3.2 锁定不存在的值
-- 查询存在的值 12
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT PS_CURRENT_THREAD_ID() THREAD_ID ,t.* FROM locktest t WHERE t.f1=12  FOR UPDATE;
Empty set (0.00 sec)

查询加锁情况:

在这里插入图片描述

【行2】 对ui_f1 在数据(13,13)上添加了 X,GAP 锁,这其实就是一个 record lock和gap lock 的组合

这是个 next key lock,锁定的范围应该是 (11,13]

我们再开启一个连接验证一下锁定的范围:

-- 插入9 ok
mysql> INSERT INTO locktest (id,f1,f2,f3) VALUES (9,9,9,9);
Query OK, 1 row affected (0.00 sec)
-- 插入12 阻塞
INSERT INTO locktest (id,f1,f2,f3) VALUES (12,12,12,12);
-- 插入 14 ok
mysql> INSERT INTO locktest (id,f1,f2,f3) VALUES (14,14,14,14);
Query OK, 1 row affected (0.00 sec)

4.4 二级唯一索引范围查询

验证完唯一索引的等值查询加锁情况,我们开始验证范围查询

4.4.1 单范围查询
START TRANSACTION;
mysql> SELECT PS_CURRENT_THREAD_ID() THREAD_ID ,t.* FROM locktest t WHERE t.f1>11  FOR UPDATE;
+-----------+----+----+----+----+
| THREAD_ID | id | f1 | f2 | f3 |
+-----------+----+----+----+----+
|        44 | 13 | 13 | 13 | 13 |
|        44 | 20 | 20 | 20 | 20 |
+-----------+----+----+----+----+
2 rows in set (0.00 sec)

加锁信息如下:

在这里插入图片描述

4.4.2 双范围查询
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT PS_CURRENT_THREAD_ID() THREAD_ID ,t.* FROM locktest t WHERE t.f1>11 AND t.f1<20  FOR UPDATE;
+-----------+----+----+----+----+
| THREAD_ID | id | f1 | f2 | f3 |
+-----------+----+----+----+----+
|        44 | 13 | 13 | 13 | 13 |
+-----------+----+----+----+----+
1 row in set (0.00 sec)

加锁信息如下图:

在这里插入图片描述

4.4.3 不存在的双范围查询
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> -- 记录 12 和21 都不存在
mysql> SELECT * FROM locktest t WHERE t.f1>=12 AND t.f1<=21 FOR UPDATE;
+----+----+----+----+
| id | f1 | f2 | f3 |
+----+----+----+----+
| 13 | 13 | 13 | 13 |
| 20 | 20 | 20 | 20 |
+----+----+----+----+
2 rows in set (0.00 sec)

加锁信息如下:

在这里插入图片描述

4.5 非唯一索引等值查询

这次我们对 f2 字段操作,这个一个二级非唯一索引字段

4.5.1 锁定存在的值
-- 查询存在的值 11
START TRANSACTION;

SELECT PS_CURRENT_THREAD_ID() THREAD_ID ,t.* FROM locktest t WHERE t.f2=11  FOR UPDATE ;
-- 当前线程THREAD_ID=44
+-----------+----+----+----+----+
| THREAD_ID | id | f1 | f2 | f3 |
+-----------+----+----+----+----+
|        44 | 11 | 11 | 11 | 11 |
+-----------+----+----+----+----+
1 row in set (0.0 sec)

查询锁的信息,发现有4个锁,如下图所示:

在这里插入图片描述

【行号1】 是一个表级的意向锁

【行号2】 是一个加在 二级索引 i_f2 上的 record 锁,锁类型为 X(排他), 值得注意的是 LOCK_DATA为【11,11】 ,我们知道二级索引的record 组成为(key,主键),所以第一个11 是二级索引字段f1 的值,而第二个11 是主键的值

【行号3】 是一个主键索引上的 排他record 锁

【行号4】 是一个 next key lock,因为 这是一个组合锁(X,GAP),锁定的数据为(13,13),也因为 13 是我们查询条件11 的下一个key

综上来看,加锁的范围是 (11,13]

也就是说对于二级非唯一索引的等值查询也会产生 next key lock

我们用以下sql 验证以下加锁范围

-- 启动一个新窗口执行以下操作

-- 插入 <11 的数据
mysql> INSERT INTO locktest (id,f1,f2,f3) VALUES (9,9,9,9);
Query OK, 1 row affected (0.00 sec)

-- 插入 =11 的数据 ,阻塞
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO locktest (id,f1,f2,f3) VALUES (111,111,11,11);

在这里插入图片描述

注意 【行2】 的 X,GAP,INSERT_INTENTION 无法获取锁 正在WATING

-- 插入>11 的数据,阻塞

START TRANSACTION;
INSERT INTO locktest (id,f1,f2,f3) VALUES (12,12,12,12);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ozkmj4KQ-1651735032664)(./assets/20220505141220-image.png)]

-- 插入 =13 的数据,不阻塞,这说明  在13 上的X,GAP 锁并不阻止 13 的插入

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

mysql> INSERT INTO locktest (id,f1,f2,f3) VALUES (1313,1313,13,13);
Query OK, 1 row affected (0.00 sec)


-- 插入>13 的数据,不阻塞
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO locktest (id,f1,f2,f3) VALUES (14,14,14,14);
Query OK, 1 row affected (0.00 sec)
4.5.2 锁定不存在的值
-- 查询存在的值 12

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

mysql> SELECT PS_CURRENT_THREAD_ID() THREAD_ID ,t.* FROM locktest t WHERE t.f2=12  FOR UPDATE;
Empty set (0.00 sec)

查询加锁情况:

在这里插入图片描述

【行2】 对 i_f2 在数据(13,13)上添加了 X,GAP 锁,这其实就是一个 record lock和gap lock 的组合

这是个 next key lock,锁定的范围应该是 (11,13]

4.6 非唯一索引范围查询

验证完 非唯一索引的等值查询加锁情况,我们开始验证范围查询

4.6.1 单范围查询
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT PS_CURRENT_THREAD_ID() THREAD_ID ,t.* FROM locktest t WHERE t.f2>11  FOR UPDATE;
+-----------+----+----+----+----+
| THREAD_ID | id | f1 | f2 | f3 |
+-----------+----+----+----+----+
|        44 | 13 | 13 | 13 | 13 |
|        44 | 20 | 20 | 20 | 20 |
+-----------+----+----+----+----+
2 rows in set (0.00 sec)

加锁信息如下:

在这里插入图片描述

4.6.2 双范围查询
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT PS_CURRENT_THREAD_ID() THREAD_ID ,t.* FROM locktest t WHERE t.f2>11 AND t.f2<20  FOR UPDATE;
+-----------+----+----+----+----+
| THREAD_ID | id | f1 | f2 | f3 |
+-----------+----+----+----+----+
|        44 | 13 | 13 | 13 | 13 |
+-----------+----+----+----+----+
1 row in set (0.00 sec)

加锁信息如下图:

在这里插入图片描述

4.6.3 不存在的双范围查询
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> -- 记录 12 和21 都不存在
mysql> SELECT * FROM locktest t WHERE t.f2>=12 AND t.f2<=21 FOR UPDATE;
+----+----+----+----+
| id | f1 | f2 | f3 |
+----+----+----+----+
| 13 | 13 | 13 | 13 |
| 20 | 20 | 20 | 20 |
+----+----+----+----+
2 rows in set (0.00 sec)

加锁信息如下:

在这里插入图片描述

4.7 无索引等值查询

这次我们对 f3 字段操作,这个一个 无索引字段

4.7.1 锁定存在的值
-- 查询存在的值 11
START TRANSACTION;

SELECT PS_CURRENT_THREAD_ID() THREAD_ID ,t.* FROM locktest t WHERE t.f3=11  FOR UPDATE ;
-- 当前线程THREAD_ID=44
+-----------+----+----+----+----+
| THREAD_ID | id | f1 | f2 | f3 |
+-----------+----+----+----+----+
|        44 | 11 | 11 | 11 | 11 |
+-----------+----+----+----+----+
1 row in set (0.0 sec)

查询锁的信息,发现数据库中的数据都添加了锁,如下图所示:

在这里插入图片描述

我们用以下sql 验证以下加锁范围

-- 启动一个新窗口执行以下操作

-- 插入 <11 的数据  阻塞 无法插入
mysql> INSERT INTO locktest (id,f1,f2,f3) VALUES (9,9,9,9);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GLTiJz19-1651735032673)(./assets/20220505150509-image.png)]

注意 【行2】 的 X,GAP,INSERT_INTENTION 无法获取锁 正在WATING

-- 插入 =11 的数据 ,阻塞
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO locktest (id,f1,f2,f3) VALUES (111,111,11,11);

在这里插入图片描述

-- 插入>11 的数据,阻塞

START TRANSACTION;
INSERT INTO locktest (id,f1,f2,f3) VALUES (12,12,12,12);

在这里插入图片描述

-- 插入 =13 的数据,阻塞

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

mysql> INSERT INTO locktest (id,f1,f2,f3) VALUES (1313,1313,13,13);
Query OK, 1 row affected (0.00 sec)


在这里插入图片描述

4.7.2 锁定不存在的值
-- 查询存在的值 12

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

mysql> SELECT PS_CURRENT_THREAD_ID() THREAD_ID ,t.* FROM locktest t WHERE t.f3=12  FOR UPDATE;
Empty set (0.00 sec)

查询加锁情况:

在这里插入图片描述

4.8 无索引范围查询

这里就不一一验证了,因为在无索引的情况下都是全表锁定。这也说明了加索引的重要性

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值