mysql 唯一索引 死锁_MySQL 死锁套路:唯一索引 S 锁与 X 锁的爱恨情仇
毫不夸張的說,有一半以上的死鎖問題由唯一索引貢獻,后面介紹的很多死鎖的問題都跟唯一索引有關。這次我們講一段唯一索引 S 鎖與 X 鎖的愛恨情仇
我們來看一個簡化過的例子
# 構造數據
CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10),
`level` int(11),
PRIMARY KEY (`id`),
UNIQUE KEY `uk_name` (`name`)
);
INSERT INTO `t1` (`name`, `level`) VALUES ('A',0);
# 出現問題的sql語句如下,并發情況下就會出現死鎖
INSERT ignore INTO `t1` (`name`, `level`) VALUES ('A',0);
update t1 set level = 1 where name = "A";
我們用之前介紹過的源碼分析方式,先來看下這兩條語句分別加什么鎖,然后分析死鎖形成的過程。
第一條語句
INSERT ignore INTO t1 (name, level) VALUES ('A',0);
在調試中得到的結果如下
可以看到這條語句對唯一鍵 uk_name 加共享鎖(S鎖),而且成功。
第二條語句
update t1 set level = 1 where name = "A"; 通過唯一鍵更新數據庫字段。
這種情況在之前的文章已經介紹過,會對唯一索引加 X 鎖,然后對主鍵索引加 X 鎖
這樣就可以非常輕松的復現死鎖的問題了,步驟如下
開啟兩個 session,分別 begin
session1 執行INSERT ignore INTO t1 (name, level) VALUES ('A',0);
session2 執行INSERT ignore INTO t1 (name, level) VALUES ('A',0);
session1 執行update t1 set level = 1 where name = "A"; 進入等待狀態
session2 執行update t1 set level = 1 where name = "A";,死鎖產生,被回滾,同時事務 1 執行成功
詳細的鎖狀態變化如下
t1
t2
備注
INSERT IGNORE INTO
-
t1成功獲得uk的S鎖 DB_SUCCESS
-
INSERT IGNORE INTO
t2成功獲得uk的S鎖 DB_SUCCESS
UPDATE
-
t1嘗試獲得uk的X鎖,但沒有成功,處于等待狀態 DB_LOCK_WAIT
-
UPDATE
t2嘗試獲得uk的X鎖,發現死鎖產生 DB_DEADLOCK
-
Deadlock
t2釋放S鎖
成功
-
-
死鎖日志如下:
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的mysql 唯一索引 死锁_MySQL 死锁套路:唯一索引 S 锁与 X 锁的爱恨情仇的全部內容,希望文章能夠幫你解決所遇到的問題。