濮阳杆衣贸易有限公司

主頁 > 知識庫 > MySQL InnoDB中的鎖機(jī)制深入講解

MySQL InnoDB中的鎖機(jī)制深入講解

熱門標(biāo)簽:昌德訊外呼系統(tǒng) 天津公司外呼系統(tǒng)軟件 百度地圖標(biāo)注要什么軟件 徐涇鎮(zhèn)騰訊地圖標(biāo)注 自己做地圖標(biāo)注需要些什么 400電話申請廠家現(xiàn)貨 中國地圖標(biāo)注公司 電話機(jī)器人的價(jià)格多少錢一個(gè)月 福建外呼電銷機(jī)器人加盟

寫在前面

數(shù)據(jù)庫本質(zhì)上是一種共享資源,因此在最大程度提供并發(fā)訪問性能的同時(shí),仍需要確保每個(gè)用戶能以一致的方式讀取和修改數(shù)據(jù)。鎖機(jī)制(Locking)就是解決這類問題的最好武器。

首先新建表 test,其中 id 為主鍵,name 為輔助索引,address 為唯一索引。

CREATE TABLE `test` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` int(11) NOT NULL,
 `address` int(11) NOT NULL,
 PRIMARY KEY (`id`),
 UNIQUE KEY `idex_unique` (`address`),
 KEY `idx_index` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4;

INSERT 方法中的行鎖

可見,如果兩個(gè)事務(wù)先后對主鍵相同的行記錄執(zhí)行 INSERT 操作,因?yàn)槭聞?wù) A 先拿到了行鎖,事務(wù) B 只能等待直到事務(wù) A 提交后行鎖被釋放。同理,如果針對唯一索引字段 address 進(jìn)行插入操作,也需要獲取行鎖,圖同主鍵插入過程類似,不再重復(fù)。

但是,如果兩個(gè)事務(wù)都針對輔助索引字段 name 進(jìn)行插入,不需要等待獲取鎖,因?yàn)檩o助索引字段即使值相同,在數(shù)據(jù)庫中也是操作不同的記錄行,不會沖突。

Update 方法與 Insert 方法結(jié)果類似。

SELECT FOR UPDATE 下的表鎖與行鎖

事務(wù) A SELECT FOR UPDATE 語句會拿到表 test 的 Table Lock,此時(shí)事務(wù) B 去執(zhí)行插入操作會阻塞,直到事務(wù) A 提交釋放表鎖后,事務(wù) B 才能獲取對應(yīng)的行鎖執(zhí)行插入操作。

但是如果事務(wù) A 的 SELECT FOR UPDATE 語句緊跟 WHERE id = 1 的話,那么這條語句只會獲取行鎖,不會是表鎖,此時(shí)不阻塞事務(wù) B 對于其他主鍵的修改操作

輔助索引下的間隙鎖

先看下 test 表下的數(shù)據(jù)情況:

mysql> select * from test;
+----+------+---------+
| id | name | address |
+----+------+---------+
| 3 | 1 |  3 |
| 6 | 1 |  2 |
| 7 | 2 |  4 |
| 8 | 10 |  5 |
+----+------+---------+
4 rows in set (0.00 sec)

間隙鎖可以說是行鎖的一種,不同的是它鎖住的是一個(gè)范圍內(nèi)的記錄,作用是避免幻讀,即區(qū)間數(shù)據(jù)條目的突然增減。解決辦法主要是:

  • 防止間隙內(nèi)有新數(shù)據(jù)被插入,因此叫間隙鎖
  • 防止已存在的數(shù)據(jù),在更新操作后成為間隙內(nèi)的數(shù)據(jù)(例如更新 id = 7 的 name 字段為 1,那么 name = 1 的條數(shù)就從 2 變?yōu)?3)

InnoDB 自動使用間隙鎖的條件為:

  • Repeatable Read 隔離級別,這是 MySQL 的默認(rèn)工作級別
  • 檢索條件必須有索引(沒有索引的話會走全表掃描,那樣會鎖定整張表所有的記錄)

當(dāng) InnoDB 掃描索引記錄的時(shí)候,會首先對選中的索引行記錄加上行鎖,再對索引記錄兩邊的間隙(向左掃描掃到第一個(gè)比給定參數(shù)小的值, 向右掃描掃描到第一個(gè)比給定參數(shù)大的值, 以此構(gòu)建一個(gè)區(qū)間)加上間隙鎖。如果一個(gè)間隙被事務(wù) A 加了鎖,事務(wù) B 是不能在這個(gè)間隙插入記錄的。

我們這里所說的 “間隙鎖” 其實(shí)不是 GAP LOCK,而是 RECORD LOCK + GAP LOCK,InnoDB 中稱之為 NEXT_KEY LOCK

下面看個(gè)例子,我們建表時(shí)指定 name 列為輔助索引,目前這列的取值有 [1,2,10]。間隙范圍有 (-∞, 1]、[1,1]、[1,2]、[2,10]、[10, +∞)

Round 1:

  • 事務(wù) A SELECT ... WHERE name = 1 FOR UPDATE;
  • 對 (-∞, 2) 增加間隙鎖
  • 事務(wù) B INSERT ... name = 1 阻塞
  • 事務(wù) B INSERT ... name = -100 阻塞
  • 事務(wù) B INSERT ... name = 2 成功
  • 事務(wù) B INSERT ... name = 3 成功

Round 2:

  • 事務(wù) A SELECT ... WHERE name = 2 FOR UPDATE;
  • 對 [1, 10) 增加間隙鎖
  • 事務(wù) B INSERT ... name = 1 阻塞
  • 事務(wù) B INSERT ... name = 9 阻塞
  • 事務(wù) B INSERT ... name = 10 成功
  • 事務(wù) B INSERT ... name = 0 成功

Round 3:

  • 事務(wù) A SELECT ... WHERE name = 2 FOR UPDATE;
  • 對 (-∞, +∞) 增加間隙鎖
  • 事務(wù) B INSERT ... name = 3 阻塞
  • 事務(wù) B INSERT ... name = 300 阻塞
  • 事務(wù) B INSERT ... name = -300 阻塞

InnoDB 鎖機(jī)制總結(jié)

參考資料

  • 《MySQL 技術(shù)內(nèi)幕 InnoDB 存儲引擎》第二版 姜承堯著
  • About MySQL InnoDB's Lock

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對腳本之家的支持。

您可能感興趣的文章:
  • MySQL查看和修改事務(wù)隔離級別的實(shí)例講解
  • Mysql事務(wù)隔離級別之讀提交詳解
  • MySQL四種事務(wù)隔離級別詳解
  • MySQL 四種事務(wù)隔離級別詳解及對比
  • 深入解析MySQL的事務(wù)隔離及其對性能產(chǎn)生的影響
  • MySQL中Innodb的事務(wù)隔離級別和鎖的關(guān)系的講解教程
  • MySQL數(shù)據(jù)庫事務(wù)隔離級別介紹(Transaction Isolation Level)
  • MySQL鎖機(jī)制與用法分析
  • 深入理解Mysql事務(wù)隔離級別與鎖機(jī)制問題

標(biāo)簽:陜西 昌都 梅河口 荊門 鄂爾多斯 黔西 駐馬店 北京

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《MySQL InnoDB中的鎖機(jī)制深入講解》,本文關(guān)鍵詞  MySQL,InnoDB,中的,鎖,機(jī)制,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《MySQL InnoDB中的鎖機(jī)制深入講解》相關(guān)的同類信息!
  • 本頁收集關(guān)于MySQL InnoDB中的鎖機(jī)制深入講解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    瑞安市| 昆山市| 抚州市| 白朗县| 山东| 玛沁县| 唐海县| 台湾省| 曲水县| 盈江县| 余干县| 房产| 南漳县| 盘山县| 芒康县| 阜平县| 宝鸡市| 孟连| 蒙阴县| 贺州市| 噶尔县| 疏勒县| 马关县| 鸡西市| 东乌珠穆沁旗| 周宁县| 甘孜县| 石屏县| 云安县| 泸西县| 寻乌县| 鄂尔多斯市| 安溪县| 高淳县| 北川| 海原县| 丰城市| 交口县| 连江县| 乐至县| 旬邑县|