1、沒有鎖CASE
# 8.0.18
# RC
CREATE TABLE `t3` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10) COLLATE utf8mb4_bin DEFAULT NULL,
`age` int(11) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`)
) ENGINE=InnoDB
2、唯一鍵死鎖CASE1
# 8.0.18
# RC
CREATE TABLE `t2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10) COLLATE utf8mb4_bin DEFAULT NULL,
`age` int(11) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
UNIQUE KEY `udx_name` (`name`),
KEY `idx_name` (`name`)
) ENGINE=InnoDB
死鎖產生的原因是:
- S1對(2,2)記錄加X鎖,
- S2/S3需要唯一鍵沖突檢測,需要加S鎖,由於X鎖的存在,S鎖的獲取被阻塞。
- S1提交或者回滾,因為S鎖兼容,S2/S3都獲得S鎖,都希望得到X鎖,發生死鎖。
為什么S2/S3要加S鎖,而不是直接等待X鎖
- S2/S3 在插入之前判斷到了唯一鍵沖突,當前讀模式
3、唯一鍵死鎖CASE2
# 隔離級別RC
# 版本8.0.18
CREATE TABLE `t1` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(10) COLLATE utf8mb4_bin DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB
insert into t1 select 1,'a',1;
事務 1 持有uk_name 唯一索引上的 S 鎖(共享鎖)
事務 1 想獲取 uk_name 唯一索引上的 X 鎖 (非 gap 鎖的記錄鎖)
事務 2 持有uk_name 唯一索引上的 S 鎖(共享鎖)
事務 2 想獲得 uk_name 唯一索引上的 X 鎖(非 gap 鎖的記錄鎖)
4、唯一鍵死鎖CASE3
# 隔離級別RC
# 版本8.0.18
CREATE TABLE `t1` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(10) COLLATE utf8mb4_bin DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB;
insert into t1 select 1,'a',1;
show engine innodb status
S2 HOLDS THE LOCK(S),WAITING FOR lock_mode X
S1 HOLDS THE LOCK(S): WAITING FOR lock_mode X