行級鎖每次操作均會鎖定對應的行資料,鎖定粒度最小,致使鎖衝突發生的可能性最低,因而併發度最高。它被應用於 InnoDB 儲存引擎之中,要知道,InnoDB 的資料是依據索引來組織的,行鎖透過對索引上的索引項加鎖來實現,並非針對記錄加鎖。
同時,InnoDB 行鎖包含共享鎖(S)和排他鎖(X) ,而行鎖的共享鎖和排他鎖還能夠繼續細分成為三類:記錄鎖、間隙鎖與臨鍵鎖。
記錄鎖(Record Lock)
作用:鎖定表中的單行記錄,防止其他事務對其進行update或delete。
情況:當執行精確匹配查詢(例如
WHERE id = 1
)並且查詢的索引是唯一索引時,會對匹配的行加記錄鎖。示例:假設有表
students
,其中id
是主鍵,事務 A 執行SELECT * FROM students WHERE id = 15 FOR UPDATE;
,此時就會對id = 15
的這行資料加記錄鎖。圖示:
間隙鎖(Gap Lock)
作用:鎖定一個範圍,但不包含記錄本身,防止其他事務在這個間隙上insert,主要用於防止幻讀。
情況:在可重複讀隔離級別下,對於範圍查詢(如
WHERE id > 5
),如果查詢的索引不是唯一索引,會使用間隙鎖。示例:事務 B 執行
SELECT * FROM students WHERE age > 20 FOR UPDATE;
,假設age
列上沒有唯一索引,此時會對age
值大於 20 的間隙加間隙鎖。圖示:
臨鍵鎖(Next-Key Lock)
作用:是記錄鎖和間隙鎖的組合,既鎖住記錄,又鎖住記錄前面的間隙。
情況:在可重複讀隔離級別下,當使用範圍查詢且查詢的索引是唯一索引時,會使用臨鍵鎖。
示例:事務 C 執行
SELECT * FROM students WHERE id >= 20 FOR UPDATE;
,如果id
是唯一索引,會對id >= 20
的範圍加臨鍵鎖。圖示:
行鎖
InnoDB的行鎖包含共享鎖(S)和排他鎖(X),在實現方式上表現為記錄鎖、間隙鎖、臨鍵鎖。
共享鎖(S 鎖):允許其他事務同時讀取被鎖定的資料,但不允許修改。
排他鎖(X 鎖):則具有排他性,不允許其他事務獲取共享鎖或排他鎖來訪問被鎖定的資料。
兩種鎖的相容情況如下:
鎖型別 | 共享鎖(S 鎖) | 排他鎖(X 鎖) |
---|---|---|
共享鎖(S 鎖) | 相容(✔) | 衝突(×) |
排他鎖(X 鎖) | 衝突(×) | 衝突(×) |
常見的SQL,加鎖情況:
SQL | 行鎖型別 | 加鎖情況 |
---|---|---|
SELECT | 無鎖 | 沒有任何加鎖 |
SELECT ... LOCK IN SHARE MODE | 共享鎖(S 鎖) | 需要在SELECT 查詢末尾加上‘LOCK IN SHARE MODE’ |
SELECT ... FOR UPDATE | 排他鎖(X 鎖) | 需要在SELECT 查詢末尾加上‘FOR UPDATE’ |
INSERT | 排他鎖(X 鎖) | 自動會加上排他鎖 |
UPDATE | 排他鎖(X 鎖) | 自動會加上排他鎖 |
DELETE | 排他鎖(X 鎖) | 自動會加上排他鎖 |
總結
總之,InnoDB 豐富多樣的行鎖機制,從共享鎖與排他鎖的大分類,到記錄鎖、間隙鎖和臨鍵鎖的具體形式,為資料庫的事務處理和併發操作提供了精細且可靠的控制手段。熟悉並駕馭這些行鎖,是實現高效能、穩定可靠的資料庫系統的重要基石。