引言
????????鎖是數據庫管理并發訪問的另一種核心機制,與 MVCC 相輔相成。本文將系統梳理 MySQL InnoDB 中鎖的粒度、類型和工作原理,并深入探討它如何與事務隔離級別配合,共同保障數據的一致性和完整性。
一、 鎖的粒度:由粗到細
????????InnoDB 支持多種粒度的鎖,允許系統在鎖開銷和數據安全性之間進行權衡:
-
全局鎖:鎖定整個數據庫實例,主要用于全庫邏輯備份,影響巨大。
-
表級鎖:鎖定整張表,主要包括:
-
元數據鎖 (MDL):由 Server 層實現,保證讀寫的表結構一致性。
-
意向鎖 (Intention Locks):一種表級鎖,用于快速判斷表內是否有行鎖。它表明“一個事務想要在表中的某些行上獲取共享鎖或排他鎖”。
-
意向共享鎖 (IS):事務打算給某些行加S鎖。
-
意向排他鎖 (IX):事務打算給某些行加X鎖。
-
-
AUTO-INC 鎖:一種特殊的表級鎖,用于在插入時生成自增列的值。在 MySQL 8.0 中,輕量級模式已大幅減少其影響。
-
-
行級鎖:InnoDB 并發能力的核心,鎖定索引記錄。
二、 行級鎖的三種算法
????????行鎖是 InnoDB 的精髓,它包含三種算法,用于在不同場景下防止幻讀和數據沖突:
-
記錄鎖 (Record Lock):鎖定索引中的一條具體記錄。
-
間隙鎖 (Gap Lock):鎖定索引記錄之間的間隙(開區間),防止其他事務在這個間隙中插入新記錄,從而有效防止幻讀。
-
臨鍵鎖 (Next-Key Lock):記錄鎖 + 間隙鎖的組合,鎖定一個記錄及其前面的間隙(左開右閉區間)。它是 InnoDB 在 可重復讀 (RR) 隔離級別下默認的行鎖算法。
三、 鎖的兼容性與死鎖
-
共享鎖 (S) 與排他鎖 (X):基本的行鎖類型。
-
S鎖(讀鎖):允許其他事務讀,但不能寫。
SELECT ... LOCK IN SHARE MODE
會加 S鎖。 -
X鎖(寫鎖):不允許其他事務讀(當前讀)或寫。
UPDATE
,DELETE
,INSERT
,SELECT ... FOR UPDATE
會加 X鎖。 -
S鎖與S鎖兼容,S鎖與X鎖、X鎖與X鎖互斥。
-
-
死鎖:不同的事務以不同的順序請求和持有鎖,導致互相等待。InnoDB 有死鎖檢測機制,會自動選擇回滾其中一個代價較小的事務。
四、 鎖與隔離級別的實戰
????????鎖的使用策略與隔離級別密不可分:
-
READ COMMITTED (RC):
-
快照讀:使用 MVCC,無鎖。
-
當前讀(
FOR UPDATE
等)及寫操作:僅使用記錄鎖。因為不加間隙鎖,所以無法避免幻讀。
-
-
REPEATABLE READ (RR):
-
快照讀:使用 MVCC,無鎖。
-
當前讀及寫操作:使用臨鍵鎖(Next-Key Lock),通過在搜索范圍內加鎖,徹底杜絕幻讀。(特例:唯一索引的唯一查詢會退化為記錄鎖)。
-
-
SERIALIZABLE (可串行化):
-
所有讀操作(即使是普通 SELECT)都會自動轉換為
SELECT ... LOCK IN SHARE MODE
,即加共享鎖。讀寫嚴重互斥,并發性能最低。
-
五、 特殊鎖:插入意向鎖 (Insert Intention Locks)
????????這是一種特殊的間隙鎖,不是表級意向鎖。它在執行 INSERT
操作前設置,表示想往某個間隙里插入一條記錄。它的存在是為了提高并發插入的性能:
-
多個事務可以在同一個間隙上同時持有插入意向鎖(只要插入的位置不同)。
-
但它會與獨占的間隙鎖/臨鍵鎖沖突。這正是防止幻讀的關鍵:一個事務持有間隙鎖,另一個事務的插入意向鎖就會被阻塞。
?更多資料:0voice · GitHub