MySQL的鎖分類

一、簡述

數據庫的鎖是在多線程高并發的情況下用來保證數據穩定性和一致性的一種機制。MySQL 根據底層存儲引擎的不同,鎖的支持粒度和實現機制也不同。MyISAM 只支持表鎖,InnoDB 支持行鎖和表鎖。目前 MySQL 默認的存儲引擎是 InnoDB,這里主要介紹 InnoDB 的鎖。InnoDB 存儲引擎有兩大優點:一是支持事務;二是支持行鎖。

在高并發的情況下,MySQL 事務的并發處理會帶來幾個問題臟讀、不可重復讀、幻讀。由于高并發事務帶來這幾個問題,所以就產生了事務的隔離級別

二、MySQL 常見的幾種鎖機制

1??實現思想

  1. 樂觀鎖
  2. 悲觀鎖

2??鎖粒度

  1. 表級鎖(table lock)
  2. 行級鎖(row lock)

3??意向鎖【表級鎖(table lock)】

意向鎖(Intention Locks)分為意向共享鎖(IS)和意向排他鎖(IX),依次表示接下來的一個事務將會獲得共享鎖還是排他鎖。意向鎖不需要顯示的獲取,在獲取共享鎖或者排他鎖的時候會自動的獲取,也就是說,如果要獲取共享鎖或者排他鎖,則一定是先獲取到了意向共享鎖或者意向排他鎖。 意向鎖不會鎖住任何東西,除非有進行全表請求的操作,否則不會鎖住任何數據。存在的意義只是用來表示有事務正在鎖某一行的數據,或者將要鎖某一行的數據。原文:Intention locks are table-level locks that indicate which type of lock (shared or exclusive) a transaction requires later for a row in a table.

IS 和 IX是表級鎖,不會和行級的 X,S 鎖發生沖突。只會和表級的 X,S 發生沖突。橫向是已經持有的鎖,縱向是正在請求的鎖:

4??讀寫鎖【行級鎖(row lock)】

讀寫鎖(ReadWriteLock)即共享鎖和排他鎖。InnoDB 通過共享鎖和排他鎖兩種方式實現了標準的行鎖。共享鎖(S 鎖):允許事務獲得鎖后去讀數據。排他鎖(X 鎖):允許事務獲得鎖后去更新或刪除數據。一個事務獲取的共享鎖(S)后,允許其他事務獲取S鎖,此時兩個事務都持有共享鎖(S),但是不允許其他事務獲取X鎖。如果一個事務獲取的排他鎖(X),則不允許其他事務獲取S或者X鎖,必須等到該事務釋放鎖后才可以獲取到。

e.g.:
LOCK TABLE mchopin READ;用讀鎖鎖表,會阻塞其他事務修改表數據,但不會阻塞其他事務讀該表。
LOCK TABLE mchopin WRITE;用寫鎖鎖表,會阻塞其他事務讀和寫。
select * from mchopin where id = 3 lock in share mode;讀行鎖,僅對一行數據加了讀鎖。
select * from mchopin where id = 3 for update;寫行鎖,僅對一行數據加了寫鎖。

# T1
START TRANSACTION WITH CONSISTENT SNAPSHOT;
SELECT * FROM mchopin WHERE category_no = 2 lock in SHARE mode; //共享鎖
SELECT * FROM mchopin WHERE category_no = 2 for UPDATE; //排他鎖
COMMIT;

# T2
START TRANSACTION WITH CONSISTENT SNAPSHOT;
SELECT * FROM mchopin WHERE mchopin_no = 2 lock in SHARE mode; //共享鎖
UPDATE mchopin set mchopin_name = '動漫' WHERE mchopin_no = 2; //排他鎖
COMMIT;

5??【記錄鎖(record Locks)】
鎖住某一行,如果表存在索引,那么記錄鎖是鎖在索引上的,如果表沒有索引,那么 InnoDB 會創建一個隱藏的聚簇索引加鎖。所以在進行查詢的時候盡量采用索引進行查詢,這樣可以降低鎖的沖突。

6??【間隙鎖(Gap Locks)】
間隙鎖是一種記錄行與記錄行之間存在空隙或在第一行記錄之前或最后一行記錄之后產生的鎖。間隙鎖可能占據的單行,多行或者是空記錄。通常的情況是采用范圍查找的時候,比如在學生成績管理系統中,如果此時有學生成績 60,72,80,95,一個老師要查下成績大于 72 的所有同學的信息,采用的語句是select * from student where grade > 72 for update,這個時候 InnoDB 鎖住的不僅是 80,95,而是所有在 72-80,80-95,以及 95 以上的所有記錄。為什么會這樣呢?因為不鎖住這些行,另一個事務在此時插入了一條分數大于 72 的記錄,會導致第一次的事務兩次查詢的結果不一樣,出現了幻讀。所以為了在滿足事務隔離級別的情況下需要鎖住所有滿足條件的行。

  1. 加鎖點,不是加在記錄上的,而是加在兩條記錄之間的位置。
  2. 作用:兩次當前讀返回的是完全相同的記錄。

幻讀和不可重復讀的關鍵點在于,幻讀是數據增加了,而不可重復讀是數據修改或刪除了。從鎖上來分析,幻讀的關鍵是 GAP 鎖,而不可重復讀的關鍵是行鎖。

7??【Next-Key Locks】
NK 是一種記錄鎖和間隙鎖的組合鎖。是 3 和 4 的組合形式,既鎖住行也鎖住間隙。并且采用的左開右閉的原則。InnoDB 對于查詢都是采用這種鎖的。
舉個例子:

CREATE TABLE `xxp` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `uid` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_uid` (`uid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO `xxp`(uid) VALUES (1);
INSERT INTO `xxp`(uid) VALUES (2);
INSERT INTO `xxp`(uid) VALUES (3);
INSERT INTO `xxp`(uid) VALUES (6);
INSERT INTO `xxp`(uid) VALUES (10);

# T1
START TRANSACTION WITH CONSISTENT SNAPSHOT; //1
SELECT * FROM xxp WHERE uid = 6 for UPDATE; //2
COMMIT;  //5

# T2
START TRANSACTION WITH CONSISTENT SNAPSHOT;  //3
INSERT INto xxp(uid) VALUES(11);
INSERT INto xxp(uid) VALUES(5);  //4
INSERT INto xxp(uid) VALUES(7);
INSERT INto xxp(uid) VALUES(8);
INSERT INto xxp(uid) VALUES(9);
SELECT * FROM xxp WHERE uid = 6 for UPDATE;
COMMIT;

ROLLBACK;

按照上面 1,2,3,4 的順序執行會發現第 4 步被阻塞了,必須執行完第 5 步后才能插入成功。這里會很奇怪明明鎖住的是uid=6 的這一行,為什么不能插入 5 呢?原因就是這里采用了 next-key 的算法,鎖住的是(3,10)整個區間。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,143評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,553評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,416評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,940評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,170評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,709評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,597評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,029評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,403評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,746評論 2 370