InnoDB的鎖

本章節(jié)主要討論InnoDB所使用到的鎖的類型。注:本文主要參考Mysql 5.7的官方文檔,如果沒有特別聲明,本文提到的MySQL都是指MySQL5.7。

共享鎖和排它鎖

InnoDB實現(xiàn)標準的行級鎖定,其中有兩種類型的鎖,共享(S)鎖獨占(X)鎖。

  • 共享(S)鎖允許持有鎖的事務讀取行。
  • 獨占(X)鎖允許持有鎖的事務更新或刪除行。

如果事務T1在行r上持有共享(S)鎖,則來自某個不同事務T2的對行r的鎖的請求按如下方式處理:

  • 可以立即授予T2對S鎖的請求。 結(jié)果,T1和T2都在r上持有S鎖。
  • T2的X鎖定請求不能立即授予。

如果事務T1在行r上持有獨占(X)鎖,則不能立即授予來自某個不同事務T2的對r上任一類型的鎖的請求。 相反,事務T2必須等待事務T1釋放其對行r的鎖定。

意向鎖(Intention Locks)

InnoDB支持多種粒度鎖定,允許行鎖和表鎖共存。 例如,LOCK TABLES ... WRITE等語句在指定的表上采用獨占鎖(X鎖)。 為了實現(xiàn)多個粒度級別的鎖定,InnoDB使用意向鎖定。 意向鎖是表級鎖,它指示事務稍后對表中的行所需的鎖(共享或獨占)類型。 意向鎖有兩種類型:

  • 意向共享鎖(IS)表示事務打算在表中的各個行上設置共享鎖。
  • 意向排他鎖(IX)表示事務打算在表中的各個行上設置獨占鎖。

例如,SELECT ... LOCK IN SHARE MODE設置IS鎖定,SELECT ... FOR UPDATE設置IX鎖定。
意圖鎖定協(xié)議如下:

  • 在事務可以獲取表中某行的共享鎖之前,它必須首先在表上獲取IS鎖或者比IS鎖更強的鎖。
  • 在事務可以獲取表中某行的獨占鎖之前,它必須首先獲取表上的IX鎖

表級鎖定類型兼容性總結(jié)在以下矩陣中:

X IX S IS
X 沖突 沖突 沖突 沖突
IX 沖突 兼容 沖突 兼容
S 沖突 沖突 兼容 兼容
IS 沖突 兼容 兼容 兼容

如果請求事務與現(xiàn)有鎖兼容,則授予鎖,但如果它與現(xiàn)有鎖沖突則不會。 事務等待,直到釋放沖突的現(xiàn)有鎖。 如果鎖定請求與現(xiàn)有鎖沖突而無法授予,因為它會導致死鎖,則會發(fā)生錯誤。
意向鎖不會阻塞除完整表請求之外的任何請求(例如,LOCK TABLES ... WRITE)。 意向鎖定的主要目的是顯示某人正在鎖定行,或者要鎖定表中的行。
意向鎖的事務數(shù)據(jù)與以下SHOW ENGINE INNODB STATUS和InnoDB監(jiān)視器輸出中的內(nèi)容類似:

TABLE LOCK table `test`.`t` trx id 10080 lock mode IX

記錄鎖(Record Locks)

記錄鎖是對索引記錄的鎖定。 例如,SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE; 防止任何其他事務插入,更新或刪除t.c1的值為10的行。
即使定義了沒有索引的表,記錄鎖也始終鎖定索引記錄。 對于這種情況,InnoDB創(chuàng)建一個隱藏的聚簇索引并使用此索引進行記錄鎖定。 請參見第14.6.2.1節(jié)“聚簇和二級索引”。
記錄鎖的事務數(shù)據(jù)在SHOW ENGINE INNODB STATUS和InnoDB監(jiān)視器輸出中顯示類似于以下內(nèi)容:

RECORD LOCKS space id 58 page no 3 n bits 72 index `PRIMARY` of table `test`.`t` 
trx id 10078 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 4; hex 8000000a; asc     ;;
 1: len 6; hex 00000000274f; asc     'O;;
 2: len 7; hex b60000019d0110; asc        ;;

間隙鎖(Gap Locks)

間隙鎖是鎖定索引記錄之間的間隙,或鎖定在第一個索引記錄之前或最后一個索引記錄之后的間隙。例如,SELECT c1 FROM t WHERE c1 BETWEEN 10 AND 20 FOR UPDATE;阻止其他事務將值15插入到列t.c1中,無論列中是否已存在這個要插入的id值,因為查詢范圍所有指定的邊界值之間的間隔都被鎖定。
間隙可以覆蓋單個索引值,多個索引值,甚至可能為空。
間隙鎖是性能和并發(fā)之間權衡的產(chǎn)物,只能用于某些事務隔離級別而不是其他級別。
使用唯一索引鎖定行以搜索唯一行的語句不需要間隙鎖定。 (這不包括搜索條件僅包含多列唯一索引的某些列的情況;在這種情況下,確實會發(fā)生間隙鎖定。)例如,如果id列具有唯一索引,則以下語句僅使用索引記錄鎖定id值等于100的行,不影響其他會話是否在id值之前的間隙中插入行:

SELECT * FROM child WHERE id = 100;

如果id不是索引列或者是非唯一索引列,則該語句會鎖定前一個間隙(即id<100的這個間隙)。
此處值得注意的是,沖突鎖可以被不同的事務同時在間隙上持有。 例如,事務A可以在間隙上持有共享間隙鎖定(間隙S鎖定),而事務B在同一間隙上持有獨占間隙鎖定(間隙X鎖定)。 允許沖突間隙鎖定的原因是,如果從索引中清除記錄,則必須合并由不同事務保留在記錄上的間隙鎖定。
InnoDB中的間隙鎖是“純粹的抑制”,這意味著它們的唯一目的是防止其他事務插入間隙。 間隙鎖可以共存。 一個事務占用的間隙鎖定不會阻止另一個事務在同一個間隙上進行間隙鎖定。 共享和獨占間隙鎖之間沒有區(qū)別。 它們彼此不沖突,它們執(zhí)行相同的功能。
可以明確禁用間隙鎖定。 如果將事務隔離級別更改為READ COMMITTED或啟用innodb_locks_unsafe_for_binlog系統(tǒng)變量(現(xiàn)已棄用),則會發(fā)生這種情況。 在這些情況下,對于搜索和索引掃描禁用間隙鎖定,并且僅用于外鍵約束檢查和重復鍵檢查。
使用READ COMMITTED隔離級別或啟用innodb_locks_unsafe_for_binlog還有其他影響。 MySQL評估WHERE條件后,將釋放不匹配行的記錄鎖。 對于UPDATE語句,InnoDB執(zhí)行“半一致”讀取,以便將最新提交的版本返回給MySQL,以便MySQL可以確定該行是否與UPDATE的WHERE條件匹配。

Next-key Locks

next-key鎖是索引記錄上的記錄鎖和索引記錄之前的間隙上的間隙鎖的組合
InnoDB以這樣的方式執(zhí)行行級鎖定:當它搜索或掃描表索引時,它會在遇到的索引記錄上設置共享鎖或排它鎖。 因此,行級鎖實際上是索引記錄鎖。 索引記錄上的next-key鎖定也會影響該索引記錄之前的“間隙”。 也就是說,next-key鎖定是索引記錄鎖定加上索引記錄之前的間隙上的間隙鎖定。 如果一個會話在索引中的記錄R上具有共享或排他鎖,則另一個會話不能在索引順序中的R之前的間隙中插入新的索引記錄。
假設索引包含值10,11,13和20.此索引的可能的next-key鎖包括以下間隔,其中圓括號表示排除間隔端點,方括號表示包含端點:

(negative infinity, 10]
(10, 11]
(11, 13]
(13, 20]
(20, positive infinity)

對于最后一個間隔,next-key鎖將間隙鎖定在索引中最大值之上,而“supremum”偽記錄的值高于索引中實際的任何值。 supremum不是真正的索引記錄,因此,實際上,此next-key鎖僅鎖定最大索引值之后的間隙。
默認情況下,InnoDB在REPEATABLE READ事務隔離級別運行。 在這種情況下,InnoDB使用next-key鎖進行搜索和索引掃描,從而防止幻像行。
next-key鎖的事務數(shù)據(jù)在SHOW ENGINE INNODB STATUS和InnoDB監(jiān)視器中輸出以下類似內(nèi)容:

RECORD LOCKS space id 58 page no 3 n bits 72 index `PRIMARY` of table `test`.`t` 
trx id 10080 lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;

Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 4; hex 8000000a; asc     ;;
 1: len 6; hex 00000000274f; asc     'O;;
 2: len 7; hex b60000019d0110; asc        ;;

插入意向鎖(Insert Intention Locks)

插入意向鎖是在行插入之前由INSERT操作設置的一種間隙鎖。 該鎖定以這樣的方式表示插入的意圖:如果多個事務插入到相同索引間隙中,但是不插入間隙內(nèi)的相同位置,則不需要等待彼此。 假設存在值為4和7的索引記錄。獨立的事務分別嘗試插入值5和6,在獲取插入行上的排它鎖之前,每個事務都使用插入意向鎖來鎖定4和7之間的間隙, 但是不會導致阻塞因為行是非沖突的。
以下示例演示了在獲取插入記錄的獨占鎖之前采用插入意向鎖定的事務。 該示例涉及兩個客戶端,A和B.
客戶端A創(chuàng)建一個包含兩個索引記錄(90和102)的表,然后啟動一個事務,該事務對ID大于100的索引記錄放置獨占鎖。獨占鎖包括記錄102之前的間隙鎖:

mysql> CREATE TABLE child (id int(11) NOT NULL, PRIMARY KEY(id)) ENGINE=InnoDB;
mysql> INSERT INTO child (id) values (90),(102);

mysql> START TRANSACTION;
mysql> SELECT * FROM child WHERE id > 100 FOR UPDATE;
+-----+
| id  |
+-----+
| 102 |
+-----+

客戶端B開始事務以將記錄插入間隙。 該事務在等待獲取獨占鎖時采用插入意向鎖。

mysql> START TRANSACTION;
mysql> INSERT INTO child (id) VALUES (101);

插入意向鎖的事務數(shù)據(jù)在SHOW ENGINE INNODB STATUS和InnoDB監(jiān)視器中輸出以下類似的內(nèi)容:

RECORD LOCKS space id 31 page no 3 n bits 72 index `PRIMARY` of table `test`.`child`
trx id 8731 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 4; hex 80000066; asc    f;;
 1: len 6; hex 000000002215; asc     " ;;
 2: len 7; hex 9000000172011c; asc     r  ;;...

自增鎖(AUTO-INC Locks)

AUTO-INC鎖是由插入到具有AUTO_INCREMENT列的表中的事務所采用的特殊表級鎖。 在最簡單的情況下,如果一個事務正在向表中插入記錄,則任何其他事務必須先等待,再對該表執(zhí)行自己的插入,以便第一個事務插入的行接收連續(xù)的主鍵值。
innodb_autoinc_lock_mode配置選項控制用于自動增量鎖定的算法。 它允許您選擇如何在可預測的自動增量值序列和插入操作的最大并發(fā)之間進行權衡。

Predicate Locks for Spatial Indexes

(暫未接觸過空間列相關的數(shù)據(jù)庫概念,日后補充)

參考

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 一 綜述 MySQL 的鎖機制相較其他的數(shù)據(jù)庫比較簡單,最顯著的特點是不同的存儲引擎支持不同的鎖機制。主要有三種類...
    柯基去哪了閱讀 3,353評論 3 7
  • 筆記摘自《MYSQL技術內(nèi)幕(InnoDB存儲引擎)》 1 什么是鎖 鎖是數(shù)據(jù)庫系統(tǒng)區(qū)別于文件系統(tǒng)的一個關鍵特性。...
    10xjzheng閱讀 839評論 0 0
  • 文章導讀: 累兮,累兮,要死兮...... 本文解決問題: 1、表級鎖定(讀鎖、寫鎖) 2、行級鎖定(共享鎖、排他...
    創(chuàng)造new_world閱讀 709評論 0 1
  • 文中論述僅限于InnoDB,比較淺顯,由于沒有找到可靠可信的資料,可能存在錯誤。 首先回顧事務的分類,MySQL中...
    maxwellyue閱讀 751評論 3 2
  • 今天出現(xiàn)一個非常奇葩的問題,在內(nèi)測的時候都沒問題,但一旦給領導過目的時候,就出現(xiàn)bug,領導打開就是看不到圖標,很...
    cooqi閱讀 2,416評論 6 0

友情鏈接更多精彩內(nèi)容