論 MySql InnoDB 如何經過插入意向鎖控制併發插入

前言

在講解以前,先來思考一個問題——假設有用戶表結構以下:html

MySqlInnoDBRepeatable-Read:users(id PK, name, age KEY)mysql

id name age
1 Mike 10
2 Jone 20
3 Tony 30

首先事務 A 插入了一行數據,而且沒有 commitsql

INSERT INTO users SELECT 4, 'Bill', 15;
複製代碼

隨後事務 B 試圖插入一行數據:併發

INSERT INTO users SELECT 5, 'Louis', 16;
複製代碼

請問:post

  1. 使用了什麼鎖?
  2. 事務 B 是否會被事務 A 阻塞?

預備知識

在瞭解插入意向鎖以前,強烈建議先了解一下意向鎖間隙鎖ui

  1. 詳解 MySql InnoDB 中的三種行鎖
  2. 詳解 MySql InnoDB 中意向鎖的做用

插入意向鎖(Insert Intention Locks)

首先讓咱們來看一下 MySql 手冊 是如何解釋 InnoDB 中的插入意向鎖的:spa

An insert intention lock is a type of gap lock set by INSERT operations prior to row insertion. This lock signals the intent to insert in such a way that multiple transactions inserting into the same index gap need not wait for each other if they are not inserting at the same position within the gap. Suppose that there are index records with values of 4 and 7. Separate transactions that attempt to insert values of 5 and 6, respectively, each lock the gap between 4 and 7 with insert intention locks prior to obtaining the exclusive lock on the inserted row, but do not block each other because the rows are nonconflicting.code

插入意向鎖是在插入一條記錄行前,由 INSERT 操做產生的一種間隙鎖。該鎖用以表示插入意向,當多個事務在同一區間(gap)插入位置不一樣的多條數據時,事務之間不須要互相等待。假設存在兩條值分別爲 4 和 7 的記錄,兩個不一樣的事務分別試圖插入值爲 5 和 6 的兩條記錄,每一個事務在獲取插入行上獨佔的(排他)鎖前,都會獲取(4,7)之間的間隙鎖,可是由於數據行之間並不衝突,因此兩個事務之間並不會產生衝突(阻塞等待)。htm

總結來講,插入意向鎖的特性能夠分紅兩部分:索引

  1. 插入意向鎖是一種特殊的間隙鎖 —— 間隙鎖能夠鎖定開區間內的部分記錄。
  2. 插入意向鎖之間互不排斥,因此即便多個事務在同一區間插入多條記錄,只要記錄自己(主鍵惟一索引)不衝突,那麼事務之間就不會出現衝突等待

須要強調的是,雖然插入意向鎖中含有意向鎖三個字,可是它並不屬於意向鎖而屬於間隙鎖,由於意向鎖表鎖插入意向鎖行鎖

如今咱們能夠回答開頭的問題了:

  1. 使用插入意向鎖記錄鎖
  2. 事務 A 不會阻塞事務 B

爲何不用間隙鎖

若是隻是使用普通的間隙鎖會怎麼樣呢?仍是使用咱們文章開頭的數據表爲例:

MySql,InnoDB,Repeatable-Read:users(id PK, name, age KEY)

id name age
1 Mike 10
2 Jone 20
3 Tony 30

首先事務 A 插入了一行數據,而且沒有 commit

INSERT INTO users SELECT 4, 'Bill', 15;
複製代碼

此時 users 表中存在三把鎖

  1. id 爲 4 的記錄行的記錄鎖
  2. age 區間在(10,15)的間隙鎖
  3. age 區間在(15,20)的間隙鎖

最終,事務 A 插入了該行數據,並鎖住了(10,20)這個區間。

隨後事務 B 試圖插入一行數據:

INSERT INTO users SELECT 5, 'Louis', 16;
複製代碼

由於 16 位於(15,20)區間內,而該區間內又存在一把間隙鎖,因此事務 B 別說想申請本身的間隙鎖了,它甚至不能獲取該行的記錄鎖,天然只能乖乖的等待 事務 A 結束,才能執行插入操做。

很明顯,這樣作事務之間將會頻發陷入阻塞等待插入的併發性很是之差。這時若是咱們再去回想咱們剛剛講過的插入意向鎖,就不難發現它是如何優雅的解決了併發插入的問題。

總結

  1. MySql InnoDBRepeatable-Read 的事務隔離級別下,使用插入意向鎖來控制和解決併發插入。
  2. 插入意向鎖是一種特殊的間隙鎖
  3. 插入意向鎖鎖定區間相同記錄行自己不衝突的狀況下互不排斥
相關文章
相關標籤/搜索