鎖是數據庫系統系統區別於文件系統的一個關鍵特性。
參考:https://blog.ouyangsihai.cn/mysql-de-you-yi-shen-qi-suo.html
一、lock和 latch
1. latch
latch在MySQL中是用來保證併發多線程操作操作臨界資源的鎖,
鎖定的對象線程
,是和咱們使用的Java等傳統語言中的鎖意義相近,而且沒有死鎖檢測的機制
。
2. lock
lock是MySQL中在事務中使用的鎖,
鎖定的對象是事務
,來鎖定數據庫中表、頁、行
;通常只有在事務commit或者rollback後進行釋放。lock是有死鎖機制的
,當出現死鎖時,lock有死鎖機制來解決死鎖問題:超時時間(參數innodb_lock_wait_timeout)、wait-for graph。
我們通常講的MySQL的“鎖”,一般就是說的lock。以下就是InnoDB中“鎖”的大分類:
二、lock的種類
MySQL Lock大體上可以分爲:表鎖、行鎖、意向鎖
三種。
1.共享/排他鎖
行鎖分爲
:S Lock和X Lock。S Lock :讀鎖;X Lock:寫鎖
。
兩鎖之間的兼容性如下。
X S
X 不兼容 不兼容
S 不兼容 兼容
簡單總結爲:讀鎖可以讀、不可寫;寫鎖不可讀、也不可寫。
2.意向鎖
可以參考:https://juejin.im/post/5b85124f5188253010326360
意向鎖是一種不與行級鎖衝突表級鎖,這一點非常重要。意向鎖分爲兩種:
事務要獲取某些行的 S 鎖,必須先獲得表的 IS 鎖。
SELECT column FROM table ... LOCK IN SHARE MODE;
事務要獲取某些行的 X 鎖,必須先獲得表的 IX 鎖。
SELECT column FROM table ... FOR UPDATE;
即:意向鎖是有數據引擎自己維護的
,用戶無法手動操作意向鎖,在爲數據行加共享 / 排他鎖之前,InooDB 會先獲取該數據行所在在數據表的對應意向鎖
。
InnoDB支持多粒度的鎖,即:允許表鎖和行鎖同時存在。
但是,假如表鎖覆蓋了行鎖的數據,所以表鎖和行鎖也會產生衝突。如:
trx1 BEGI
trx1 給 T1 加X鎖修改數據。
trx2 BEGIN
trx2 給 T1 加表鎖修改表結構
表鎖和行鎖之間就產生了衝突,爲了解決這種表鎖和行鎖共存的問題,就產生了意向鎖這個東西。
意向鎖:從字面意思也很好理解,就是提前表明一個“意向”
。
意向鎖僅僅是表明意向
,它其實非常弱,意向鎖之間可以相互並行,並不是排斥的
。意向鎖之間的兼容性問題:
IS IX
IS 兼容 兼容
IX 兼容 兼容
於是,上述現象就變爲了:
trx1 BEGIN
trx1 給 T1 先加IX ,然後在某一行記錄加X鎖。
trx2 BEGIN
trx2 給 T1 加表鎖X(事務被阻塞,等待加鎖成功)
trx2 修改表結構
意向鎖存在的意義是什麼呢?
”沒有意向鎖,行鎖和表鎖照樣可以共存,試問如何共存?” “查看錶中某一行存在X鎖” “如何查看呢?” 唯有全表掃描…
意向鎖的存在就是解決了“全表掃描”的性能問題
,所以,意向鎖一定是“表級”鎖,告訴整張表XXX行存在X鎖
。此時假如進行表操作就會被阻塞。
InnoDB 支持多粒度鎖,特定場景下,行級鎖可以與表級鎖共存。
意向鎖之間互不排斥,但除了 IS 與 S 兼容外
,意向鎖會與 共享鎖 /排他鎖 互斥。
IX,IS是表級鎖,不會和行級的X,S鎖發生衝突
。只會和表級的X,S發生衝突
。
意向鎖在保證併發性的前提下,實現了行鎖和表鎖共存且滿足事務隔離性的要求。
3.主鍵自增鎖
自增鎖(auto-inc Locks)是一種特殊的表級鎖
,專門針對事務插入AUTO_INCREMENT類型的列,往往就是主鍵列。可以保證主鍵的值自增是“原子操作”,不會出現一致性、唯一性問題。
4.行鎖的具體分類
InnoDB存儲引擎有以上3種行鎖算法。以上3種,都是實現在索引上的。
①記錄鎖(Record Lock)
記錄鎖(Record Lock)總是會去鎖住索引記錄。
假如沒有任何一個索引,那麼InnoDB會鎖住隱形創建的那個主鍵。
注意:這裏鎖的是索引,不一定只是主鍵索引哦,還可能是二級普通索引。
②間隙鎖(Gap Lock)
顧名思義,它會封鎖索引記錄中的“縫隙”
,防止其他事務在“縫隙”中插入數據。
它鎖定的是一個不包含索引本身的範圍。
例如以下索引數據:
間隙鎖(Gap Lock)
可以鎖的將是以下範圍
具體的範圍還要根據查詢條件不同而定。
間隙鎖開啓的事務隔離級別是 Repeatable Read
,如果把數據庫事務級別降爲Read Committed(默認是 Repeatable Read),間隙鎖則會自動失效。
③ 臨鍵鎖(Next-Key Lock)
Next-Key Lock可以說是記錄鎖(Record Lock)和間隙鎖(Gap Lock)的組合
,既封鎖了”縫隙”,又封鎖了索引本身
。
還是上面的索引數據:
臨鍵鎖(Next-Key Lock)鎖住的範圍將是:
Next-key Lock在索引具有唯一性的時候,例如主鍵索引的數據,將會降級爲記錄鎖(Read Lock),以增加併發性。
例如:
T1 T2
BEGIN; |
select * From T |
where id = 5 for update |
---------------------------------------------------------------
| BEGIN;
| Insert into t (4, xx);
---------------------------------------------------------------
| COMMIT
|
----------------------------------------------------------------
COMMIT |
|
|
-----------------------------------------------------------------
以上情況,就會把Next-key Lock降級爲記錄鎖(Read Lock)