天天看點

MySQL存儲引擎InnoDB多版本并發控制(MVCC)

注:文章并未完全深入,隻對MVCC稍作總結,如發現問題,請幫忙指出,多謝。

多版本并發控制MVCC 一、了解

  MVCC(Multi-Version Concurrency Control 多版本并發控制),根據字面意思來了解,用于并發狀況下的資料庫資料通路控制。多版本指的是為每次的資料修改儲存一個備份。不同備份對事務表現出不同的可見性。控制主要是指對儲存的多版本的可見性的控制。

  備份的作用:1、復原時使用;2、并發事務讀一緻性保證。

二、實作

1、每行中的三個隐藏字段

  • 一個6位元組的DB_TRX_ID,該字段辨別插入或者更新該行的最後一個事務的ID(注:删除也被當做更新對待,專門有一個bit的标志位辨別是否删除)。
  • 一個7位元組的DB_ROLL_PTR,該字段表示一個指針,存儲的是位址,指向rollback segment中儲存着的undo log record。
  • 一個6位元組的DB_ROW_ID,該字段表示一個行ID,每插入一個新行,該字段的值就加1。

2、字段具體功能

(1)對于DB_TRX_ID,首先要知道read view這個概念

·

 read view: 讀視圖,是事務做的快照,記錄目前活躍的其它事務資訊。

·

 read view快照時間點:對于Repeatable Read隔離級别,在第一個SELECT開始時建立快照。對于Read Committed隔離級别,每個SELECT請求均會建立快照。

每個事務都會建立一個read view,記錄目前系統的活躍事務資訊,其中有兩個比較關鍵,一個是up_limit_id(表示快照中活躍事務的最小ID),另一個是low_limit_id(表示快照中活躍事務的最大ID+1)。

·

 up_limit_id、low_limit_id 怎麼了解比較好?我把它們稱為絕對可見性上下限,up_limit_id表示絕對可見上限(但凡小于該值的,絕對是可見的),low_limit_id表示絕對不可見下限(但凡是高于該值的,絕對是不可見的)。

·

 可見性:

  在事務通路行資料的時候,會将該行所記錄的事務ID(curr_trx_id 目前記錄ID)與up_limit_id和low_limit_id比較。如果curr_trx_id < up_limit_id,那麼row對該事務可見。如果curr_trx_id >= low_limit_id,那麼row對該事務不可見。

  當up_limit_id <= curr_trx_id < low_limit_id,這個時候要将curr_trx_id和快照中的up_limit_id到low_limit_id的所有值進行比較,如果和其中某個值相等,則對目前事務不可見,否則對目前事務可見。也就是說,在執行快照的時候,事務還在活躍,并未送出,當然不可見。如果不可見怎麼取呢,這個時候DB_ROLL_PTR就發揮作用了

(2)DB_ROLL_PTR 當行資料對目前通路的事務不可見,這個時候就要去DB_ROLL_PTR指針指向的位址中去找該行對應修改前行記錄,周遊連結清單(連結清單記錄着曆次修改的值),取其中的DB_TRX_ID再來進行上述比較,直到找到一條對目前事務可見的記錄。

(3)DB_ROW_ID 在建立的表沒有指定主鍵的情況下,InnoDB會自動建立包含row ID值的聚簇索引,如果指定了主鍵,DB_ROW_ID字段值不會出現在任何索引中。也就是說,以InnoDB作為存儲引擎,不指定主鍵的話,row ID就是主鍵。

三、MVCC有什麼作用

1、最重要的一點,高并發讀寫阻塞問題得到緩解,使得讀-寫并發操作之間無需加鎖,提升并發性能。

2、可以解決髒讀、幻讀問題。

四、總結

1、MVCC是為了并發讀-寫操作無需加鎖而生,以此提高并發性能。

2、MVCC需要進行快照讀Read View來記錄并發活躍事務。

3、多版本是指對資料的每次修改都儲存一個備份。

4、儲存的備份記錄在undo log中。

5、通過可見性算法來确定記錄對事務是否可見。

6、MVCC具體實作需要三個隐藏字段配合DB_TRX_ID、DB_ROLL_PTR、DB_ROW_ID。

參考:

https://dev.mysql.com/doc/refman/5.7/en/innodb-multi-versioning.html

https://blog.csdn.net/SnailMann/article/details/94724197

https://segmentfault.com/a/1190000012650596

https://my.oschina.net/xinxingegeya/blog/505675