閱讀本文可能需要先了解下innodb的基礎知識 mysql 存儲引擎 innodb(一) 簡單介紹
加鎖分析及鎖兼容矩陣
官方文檔中對於sql語句的加鎖描述
-
SLELCT … FROM
前三種級別不加鎖,SERIALIZABLE級別下,會對SELECT 默認帶上LOCK IN SHARE MODE,S鎖 -
SELECT…FOR UPDATE / SELECT … LOCK IN SHARE MODE
掃描到的行都會加上鎖(不符合where子句條件的記錄鎖會被釋放) -
SELECT … LOCK IN SHARE MODE
在搜索遇到的所有索引記錄上加 next-key lock(S)。對於使用唯一索引搜索唯一行的語句,只需在對應的索引上加鎖(行鎖S) -
SELECT … FOR UPDATE
在搜索遇到的所有索引記錄上加 next-key lock (X)。對於使用唯一索引搜索唯一行的語句,只需在對應的索引上加鎖(行鎖X)。 -
UPDATE … WHERE
在搜索遇到的所有索引記錄上加 next-key lock (X)。對於使用唯一索引搜索唯一行的語句,只需在對應的索引上加鎖(行鎖X)。
當UPDATE修改聚集索引記錄時,對受影響的輔助索引記錄進行隱式鎖定。在插入新的二級索引記錄之前執行 duplicate check掃描時,以及在插入新的二級索引記錄時,UPDATE操作還會在受影響的二級索引記錄上獲得共享鎖。 -
DELETE FROM … WHERE …
在搜索遇到的所有索引記錄上加 next-key lock (X)。對於使用唯一索引搜索唯一行的語句,只需在對應的索引上加鎖(行鎖X)。 -
INSERT
在插入的行上設置行鎖(X)。
在插入之前,會先設置一個gap鎖,稱爲insert intention gap lock。(insert intention gap lock和insert intention gap lock是兼容的,例如現在有索引4,7;事務A,B分別要插入5,6;事務A,B在獲取X鎖之前,會獲取這個i gap,鎖定4和7的間隙,A,B彼此不會阻塞,因爲行沒有衝突。)
如果insert 的事務出現了duplicate-key error ,事務會對duplicate index record加共享鎖。這個共享鎖在併發的情況下是會產生死鎖的。
session A | session B | session C |
---|---|---|
START TRANSACTION; | ||
INSERT INTO t1 VALUES(1); | ||
insert成功,並X鎖 | START TRANSACTION; | |
· | INSERT INTO t1 VALUES(1); | START TRANSACTION; |
` | wait | INSERT INTO t1 VALUES(1); |
` | wait | |
rollback, 釋放X鎖 | ||
` | 獲取S鎖 | 獲取S鎖 |
` | 獲取X鎖沒有成功,等待session C釋放S鎖 | 獲取X鎖沒有成功,等待session B釋放S鎖 |
` |
-
INSERT … ON DUPLICATE KEY UPDATE
和INSERT的區別是,在發生duplicate key error 時,加的是X鎖,而不是S鎖。
主鍵衝突時,加的行鎖(X);唯一鍵衝突時,加的是next-key lock(X)。【前面描述出自官方文檔,但是有網上有博客說官方文檔有bug,主鍵衝突也加的是next-key lock】 -
REPLACE …
replace into 跟 insert 功能類似,不同點在於:replace into 首先嚐試插入數據到表中, 1. 如果發現表中已經有此行數據(根據主鍵或者唯一索引判斷)則先刪除此行數據,然後插入新的數據。 2. 否則,直接插入新數據。
如果插入沒有衝突,和insert一樣,否則,加next-key lock (X)
鎖的兼容矩陣
` | Gap | Insert Intention | Record | Next-Key |
---|---|---|---|---|
Gap | 兼容 | 兼容 | 兼容 | 兼容 |
Insert Intention | 衝突 | 兼容 | 兼容 | 衝突 |
Record | 兼容 | 兼容 | 衝突 | 衝突 |
Next-Key | 兼容 | 兼容 | 衝突 | 衝突 |
注:橫向是已經持有的鎖,縱向是正在請求的鎖
type | IS | IX | S | X |
---|---|---|---|---|
IS | 兼容 | 兼容 | 兼容 | 不兼容 |
IX | 兼容 | 兼容 | 不兼容 | 不兼容 |
S | 兼容 | 不兼容 | 兼容 | 不兼容 |
X | 不兼容 | 不兼容 | 不兼容 | 不兼容 |
參考:
[1] mysql官方文檔 https://dev.mysql.com/doc/refman/5.7/en/innodb-locks-set.html
[2] MySQL技術內幕:InnoDB存儲引擎
[3] http://m.elecfans.com/article/872770.html
[4] https://www.jianshu.com/p/7004f7571427