我对 MySQL 8.0 上的死锁有疑问

问题描述 投票:0回答:0

我使用的是MySQL版本

8.0.26
,事务隔离是默认值
REPEATABLE-READ
.

这是我的桌子

create table test
(
    id          int auto_increment primary key,
    a           varchar(256) null,
    b           int null,
    c           int null,
    create_time timestamp default CURRENT_TIMESTAMP null,
    constraint uni_key unique (a, b, c)
);

这是我的死锁场景

会议A 会议B 会议C
开始; 开始; 开始;
insert ignore into test(a,b,c) values ('a',1,1);
查询正常,影响 1 行(0.01 秒)
insert ignore into test(a,b,c) values ('a',1,1); insert ignore into test(a,b,c) values ('a',1,1);
(阻塞) (阻塞)
提交;
查询正常,0 行受影响,1 条警告(7.55 秒) 查询正常,0 行受影响,1 条警告(3.83 秒)
将忽略插入测试(a,b,c)值('a',2,1);
(阻塞)
将忽略插入测试(a,b,c)值('a',2,1);
查询成功,1 行受影响(5.29 秒) ERROR 1213 (40001): 尝试获取锁时发现死锁;尝试重启交易

不知为什么SessionB第二次插入会被阻塞,为什么会出现死锁

死锁后,我使用

SHOW ENGINE INNODB STATUS \G
.

------------------------
LATEST DETECTED DEADLOCK
------------------------
2023-04-25 09:42:47 140135040808704
*** (1) TRANSACTION:
TRANSACTION 15578, ACTIVE 21 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 6 lock struct(s), heap size 1128, 3 row lock(s)
MySQL thread id 33, OS thread handle 140135392589568, query id 775 localhost root update
insert ignore into test(a,b,c)values('a',2,1)

*** (1) HOLDS THE LOCK(S):
RECORD LOCKS space id 23 page no 4 n bits 72 index PRIMARY of table `manager`.`test` trx id 15578 lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;


*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 23 page no 4 n bits 72 index PRIMARY of table `manager`.`test` trx id 15578 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;


*** (2) TRANSACTION:
TRANSACTION 15579, ACTIVE 17 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 5 lock struct(s), heap size 1128, 3 row lock(s)
MySQL thread id 35, OS thread handle 140135392884480, query id 776 localhost root update
insert ignore into test(a,b,c)values('a',2,1)

*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 23 page no 4 n bits 72 index PRIMARY of table `manager`.`test` trx id 15579 lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;


*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 23 page no 4 n bits 72 index PRIMARY of table `manager`.`test` trx id 15579 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;

*** WE ROLL BACK TRANSACTION (2)

如果将事务隔离切换为 RC,则不会出现死锁错误。

我阅读了文档,但找不到我的场景的描述,也许我错过了它。

更新: 我注意到这应该将当前主键锁定为无穷大,但不知道为什么。

mysql database innodb deadlock
© www.soinside.com 2019 - 2024. All rights reserved.