MySQL唯一鍵死鎖總結分析



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

死鎖產生的原因是:

  1. S1對(2,2)記錄加X鎖,
  2. S2/S3需要唯一鍵沖突檢測,需要加S鎖,由於X鎖的存在,S鎖的獲取被阻塞。
  3. S1提交或者回滾,因為S鎖兼容,S2/S3都獲得S鎖,都希望得到X鎖,發生死鎖。

為什么S2/S3要加S鎖,而不是直接等待X鎖

  1. 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM