mysql 间隙锁 作用,MySQL一例间隙锁分析

研究间隙锁的时候碰到一个问题1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18CREATE TABLE `t2` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`a` int(11) DEFAULT NULL,

PRIMARY KEY (`id`),

KEY `idx_a` (`a`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql> select * from t2;

+----+------+

| id | a |

+----+------+

| 1 | 2 |

| 3 | 4 |

| 6 | 5 |

| 8 | 5 |

| 10 | 5 |

| 13 | 11 |

+----+------+

T1:

1

2

3

4

5

6

7

8

9

10mysql> begin;

Query OK, 0 rows affected (0.00 sec)

mysql> select * from t2 where a=4 for update;

+----+------+

| id | a |

+----+------+

| 3 | 4 |

+----+------+

1 row in set (0.00 sec)

T2:

1

2

3

4

5

6

7

8

9

10

11mysql> begin;

Query OK, 0 rows affected (0.00 sec)

mysql> insert into t2 values (4, 5);

// 超时

mysql> insert into t2 values (7, 5);

Query OK, 1 row affected (0.00 sec)

mysql> insert into t2 values (null, 5);

Query OK, 1 row affected (0.00 sec)

问题:

为什么 T2 的第一个 insert 不能执行,间隙锁锁定难道不是区间 (4, 5] 吗?例子来自:

为什么 T2 第二个 insert 不能执行。第二个和第一个的 insert 只是因为 id 不同就最终的行为不同。第三条sql也可以执行。

表的索引结构是这样的:

7c91fc4af9dbd0a19d663ed85577dbc8.png

间隙锁锁住的不是索引值的间隙,之前一直理解的是值的间隙。比如 where a=4,如果是值的间隙就是 (2, 4] 和 (4, 5],这样理解不够完整。间隙锁住应该是索引的间隙,他锁住的是 B+ 树的节点,他的语义是「如果某两个索引项之间的间隙被锁住以后,这两个索引项之间在解锁前不能再写入新的索引项」,对照 t2 表在 a 上的索引,(a=2, id=1) 和 (a=5, id=6) 之间不能再写入新的索引项。

(id=4, a=5) 不能写入是因为他落在了间隙锁的间隙内了,他会被插到 (id=3, a=4) 和 (id=6, a=5) 之间。(id=7, a=5) 能写入是因为他会被插到 (id=6, a=5) 和 (id=8, a=5) 之间,这个区间不在间隙锁的间隙内,所以可以写入。 (id=null, a=5) 能写入和 (id=7, a=5) 的原因一样,id 列指定为 Null 时 mysql 会分配个自增的 id ,这个新的 id 显然不在间隙所的间隙内。

如果是 t2 没有主键:1

2

3

4

5

6

7

8

9

10mysql> CREATE TABLE `t_noid` (

-> `a` int(11) DEFAULT NULL,

-> KEY `idx_a` (`a`)

-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Query OK, 0 rows affected (0.02 sec)

mysql>

mysql> insert into t_noid values (1), (3), (5), (8), (11);

Query OK, 5 rows affected (0.01 sec)

Records: 5 Duplicates: 0 Warnings: 0

T1:

1

2

3

4

5mysql> begin;

Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_noid where a=4 for update;

Empty set (0.00 sec)

T2:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15mysql> begin;

Query OK, 0 rows affected (0.00 sec)

mysql> insert into t_noid values (5);

Query OK, 1 row affected (0.00 sec)

mysql> insert into t_noid values (2);

Query OK, 1 row affected (0.00 sec)

mysql> insert into t_noid values (3);

^C^C -- query aborted

ERROR 1317 (70100): Query execution was interrupted

mysql> insert into t_noid values (4);

^C^C -- query aborted

ERROR 1317 (70100): Query execution was interrupted

没有主键的辅助索引是这样的:

bb8fd6c01f94b5d353131a0f8da65a9b.png

insert 5 能执行是因为隐藏的 id 会递增 7,写入 (id=7, a=5) 不在间隙内。3 和 4 都在值的间隙内,无法写入。2 不在间隙内。

资料

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值