我使用的是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,则不会出现死锁错误。
我阅读了文档,但找不到我的场景的描述,也许我错过了它。
更新: 我注意到这应该将当前主键锁定为无穷大,但不知道为什么。