mysql中InnoDB事務隔離的記錄鎖、間隙鎖和臨鍵鎖
InnoDB默認的事務隔離級別為可重復讀(Repeated Read, RR),我們當下的所有介紹都是基于這個隔離級別為前提的。
- 記錄鎖(Record Locks):鎖定單一行記錄,InnoDB 使用記錄鎖來實現(xiàn)行級鎖,這樣允許多個事務并發(fā)訪問不同的行。
- 間隙鎖(Gap Locks):InnoDB 的特性,用于鎖定一個范圍,但不包括實際的記錄。這主要用于防止幻讀(Phantom Reads)。
- 臨鍵鎖(Next-Key Locks):InnoDB 存儲引擎的一種鎖定機制,在執(zhí)行查詢語句時,根據(jù)查詢條件所鎖定的一個范圍。這個范圍中包含有間隙鎖和記錄鎖。它的設計目的是為了解決幻讀(Phantom Reads)。
記錄鎖(Record Locks)
記錄鎖,它封鎖索引記錄,例如:
select * from table where id=5 for update;
它會在id=1的索引記錄上加鎖,以阻止其他事務插入,更新,刪除id=1的這一行。
需要說明的是:
select * from table where id=5;
則是快照讀(SnapShot Read),它并不加鎖,快照讀可以參考作者這篇文章:數(shù)據(jù)庫系列:RR和RC下,快照讀的區(qū)別
間隙鎖(Gap Locks)
間隙鎖,它封鎖索引記錄中的間隔,或者第一條索引記錄之前的范圍,又或者最后一條索引記錄之后的范圍。
延續(xù)上面的那個例子繼續(xù)演示:
# 表結構 table (Id PK, Name , Company); # 表中包含四條記錄 5, Gates, Microsoft 7, Bezos, Amazon 11, Jobs, Apple 14, Elison, Oracle
執(zhí)行SQL語句如下:
select * from table where id between 7 and 13 for update;
這樣的話,會封鎖數(shù)據(jù)的區(qū)間,以防止其他事務插入id=8的記錄。
假設沒有間隙鎖,則可能夠插入成功,而之前的select事務,會發(fā)現(xiàn)檢索的結果集莫名多了一條記錄,即幻影數(shù)據(jù)。
所以間隙鎖主要目的用于防止幻讀(Phantom Reads),避免其他事務在間隔中插入數(shù)據(jù),導致 『不可重復讀』。
如果把事務的隔離級別降級為讀提交(Read Committed, RC),對,就是互聯(lián)網(wǎng)最常用的隔離級別,間隙鎖則會自動失效。
臨鍵鎖(Next-Key Locks)
臨鍵鎖(Next-Key Locks)是數(shù)據(jù)庫管理系統(tǒng)InnoDB中的一種重要鎖定機制。這種鎖是查詢時根據(jù)查詢條件鎖定的一個范圍,這個范圍包括間隙鎖和記錄鎖,左開右閉,即不鎖住左邊界,但會鎖住右邊界。臨鍵鎖的主要設計目的是為了解決所謂的“幻讀”問題。
# 左開右閉 示例 (-infinity, 1] (1, 7] (7, 9] (9, +infinity]
依然沿用上面的例子,InnoDB引擎,RR隔離級別:
-- 創(chuàng)建一個示例表 CREATE TABLE users ( Id INT PRIMARY KEY, Name VARCHAR(255) NOT NULL, Company VARCHAR(255) NOT NULL, ); -- 插入一些示例數(shù)據(jù) INSERT INTO users (id, name, company) VALUES (1, 'Alice', 'ali'); INSERT INTO users (id, name, company) VALUES (2, 'Brand', 'tencent'); INSERT INTO users (id, name, company) VALUES (3, 'Charlie', 'baidu'); -- 開始一個事務,并使用臨鍵鎖查詢數(shù)據(jù) START TRANSACTION; SELECT * FROM users WHERE id > 1 FOR UPDATE; -- 在另一個事務中嘗試插入新數(shù)據(jù),將會被阻塞直到第一個事務釋放鎖 START TRANSACTION; INSERT INTO users (id, name, age) VALUES (4, 'David', 30); COMMIT; -- 第一個事務提交后,第二個事務可以繼續(xù)執(zhí)行插入操作 COMMIT;
臨鍵鎖的主要目的,也是為了避免幻讀(Phantom Read),在事務隔離級別為可重復讀的情況下,InnoDB存儲引擎默認使用臨鍵鎖。這種鎖提供了一種有效的機制來保證在并發(fā)環(huán)境中數(shù)據(jù)的完整性和一致性。
如果把事務的隔離級別降級為RC,臨鍵鎖則也會失效。
總結
- InnoDB的索引與行記錄存儲在一起,MyISAM則是通過索引的地址查找到對應的數(shù)據(jù)記錄,效率低一些
- InnoDB的聚集索引存儲行記錄,普通索引存儲PK,所以普通索引要查詢兩次
- 記錄鎖鎖定索引關聯(lián)的具體記錄
- 間隙鎖鎖定間隔,防止間隔中被其他事務插入
- 臨鍵鎖鎖定索引記錄+間隔,防止幻讀
- select...for update加鎖的幾種情況:
- 主鍵字段:加行鎖。
- 唯一索引字段:加行鎖。
- 普通索引字段:加行鎖。
- 主鍵范圍:加多個行鎖。
- 普通字段:加表鎖。
- 查詢空數(shù)據(jù):不加鎖。
- 行鎖與表鎖的區(qū)別
- 如果事務1加了行鎖,一直未釋放鎖,事務2操作相同記錄,會一直等待直至超時。
- 如果事務1加了表鎖,一直未釋放鎖,事務2無論操作哪一行記錄,都會一直等待直到超時
到此這篇關于mysql中InnoDB事務隔離的記錄鎖、間隙鎖和臨鍵鎖的文章就介紹到這了,更多相關InnoDB的記錄鎖、間隙鎖和臨鍵鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
mysql 數(shù)據(jù)庫安裝經(jīng)驗問題匯總
這篇文章主要介紹了mysql 數(shù)據(jù)庫安裝經(jīng)驗問題匯總,本文介紹的非常詳細,具有參考借鑒價值,需要的朋友可以參考下2016-09-09mysql多行子查詢實戰(zhàn)案例(只包含不相關子查詢)
在MySQL中多行子查詢(也稱為 IN 子查詢)是指子查詢返回多行數(shù)據(jù),并且這些數(shù)據(jù)用于主查詢中的某個條件判斷,這篇文章主要介紹了mysql多行子查詢(只包含不相關子查詢)的相關資料,需要的朋友可以參考下2024-10-10