我不确定为什么会发生以下行为。我认为它必须与间隙锁定/下一键锁定有关。文档中提到了它们,但解释并不详细。
-- isolation level is Repeatable Read
-- create the table
create table t (id int primary key auto_increment, COL1 int, key idx_a(COL1));
insert into t (COL1) values(5), (10), (11), (13), (20);
select * from t;
---- ----
id | COL1
---- ----
1 | 5
2 | 10
3 | 11
4 | 13
5 | 20
-- in transaction 1
select * from t where COL1 = 13 for update;
-- in transaction 2
insert into t (COL1) values(10); -- success
insert into t (COL1) values(11); -- blocks
insert into t (COL1) values(12); -- blocks
.
.
insert into t (COL1) values(19); -- blocks
insert into t (COL1) values(20); -- success
-- in transaction 3
update t set COL1 = 11 where COL1 = 10; -- success
update t set COL1 = 12 where COL1 = 10; -- blocks
.
.
update t set COL1 = 20 where COL1 = 10; -- blocks
update t set a = 21 where a = 10; -- success
看来:
INSERT 为 COL1 锁定,值为 [11, 20)(11 到 20,不包括 20)
UPDATE 被锁定为 COL1,值为 (11, 20](11 到 20,不包括 11)
我想知道为什么 MySQL 会这样?这种锁定的一般规则是什么?
最佳答案
在 MySQL 5.7 InnoDB 下可重复读
因为COL1有一个non-unque-index,
select * from t where COL1 = 13 for update;
该语句锁定 cluster-index B+Tree record where id = 4,还锁定 COL1 index B+Tree where the record having COL1=10,并锁定 COL1 index B+Tree from (k=11, id=3 ) 到 (k=20, id=5) 与间隙锁。
insert into t (COL1) values(10); equals to : insert into t (id, COL1) values(6,10); gap lock
insert into t (COL1) values(11); equals to : insert into t (id, COL1) values(7,11); gap lock
insert into t (COL1) values(12); equals to : insert into t (id, COL1) values(8,12); gap lock
insert into t (COL1) values(19); gap lock
insert into t (COL1) values(20); equals to : insert into t (id, COL1) values(9,20);
但是看到这个条件:
CREATE TABLE `t` (
`id` int(11) NOT NULL,
`k` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_k` (`k`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8<br/>
insert into t values(2,2),(6,6);
然后插入:
1, insert into t values (1,2); success
2, insert into t values (3,2); block
3, insert into t values (5,6); block
4, insert into t values (7,6); success
如果他们都可以插入这些值在 k'B+Tree 中的位置?
所以可以看到 (k=2, id=1) 可以插入,因为它不在间隙中,也值 (k=6, id=7), (k=2, id=3) and ( k=6, id=5) 不能插入,因为它们在间隙中。
关于mysql - Mysql Gap-lock/Next-key Locks规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52399319/