天天看點

mysql innoDB的REPEATABLE READ MVCC事務實作方式

mysql大多數事務型存儲引擎實作的并不是簡單的行級鎖,一般是基于并發考慮實作多版本控制。MVCC。 一般的MVCC 分為樂觀并發控制和悲觀并發控制。 InnoDB的MVCC 是通過儲存兩個隐藏列來實作的。一個列是儲存行的建立時間,一個列是儲存行的過期時間,實際上存儲的不是時間值,而是系統版本号。每次開啟一個新的事務系統版本号就會遞增。 來看下 REPEATABLE READ 它是怎麼控制的 innoDB SELECT 會根據兩種條件來判斷每一行的記錄 a. innoDB隻查找版本早于目前事務版本的資料行,(也就是行的系統版本号小于等于事務的系統版本号),這樣可以確定事務讀取的行,要麼是在事務開始前已經存在的要麼是事務自身插入的或者修改的。 b.行的删除版本要麼未定義,要麼大于事務版本号。這個可以確定事務讀取到的行在事務開啟之前為被删除。 隻有符合上面兩個條件才會作為查詢結果。

INSERT innoDB 為新插入的每一行儲存目前系統的版本号作為行版本号。 DELETE innoDB 為删除的每一行儲存目前系統版本号作為行删除辨別 UPDATE innoDB為新插入的一條記錄,儲存目前系統版本号作為版本号,同僚儲存目前系統版本号到原來的行作為删除記錄。

儲存這兩個額外的字段,導緻了大部分讀取都不需要加鎖。 上面說了一大堆理論 咱們來推演一下 現在有A,B 兩個事務 版本号分别為1,2 資料表中資料

ID NAME CREATE_VERSION OVER_VERSION
1 ABC
2 DB

假設事務A 是 操作的方式将 ID 為1的NAME 讀取出來,更新到ID為2的NAME 字段中 假設事務B 是 操作的方式是更新事務A的NAME 字段為AAA 兩個事務開啟的順序為 A 先開啟,但是還沒讀取的時候 B 操作完成了 那麼 我們看這個瞬間這個表的結構式什麼樣子的

ID NAME CREATE_VERSION OVER_VERSION
1 ABC 2
2 DB
1 AAA 2

我們需要注意的是 UPDATE 之後他的行并沒有消除而是在新增了一行和标記了上一行在在事務2這個版本上被删除了。 是以事務A 版本号1的 select 語句來讀取的時候還是讀取的 NAME ABC的結果。 可以參照之前SELECT 的條件來讀取,咱們來推演一遍 查找條件一 系統版本号在小于目前版本的ID 1 會命中 ID 1 NAME ABC 這個選項, 查找條件二 删除版本号要麼為定義要麼大于系統版本号 顯然這邊的删除版本号定義了,而且大于了事務A的事務版本号導緻了能讀取到這個結果 上面的這個例子也就說明了能重複讀取的都是這個 ID 1 NAME ABC 的穩定結果。 實作了可重複讀。