1. 程式人生 > >MySQL的innodb引擎是如何實現MVCC的

MySQL的innodb引擎是如何實現MVCC的

innodb會為每一行新增兩個欄位,分別表示該行建立的版本刪除的版本,填入的是事務的版本號,這個版本號隨著事務的建立不斷遞增。在repeated read的隔離級別(事務的隔離級別請看這篇文章)下,具體各種資料庫操作的實現:

  • select:滿足以下兩個條件innodb會返回該行資料:
    • 該行的建立版本號小於等於當前版本號,用於保證在select操作之前所有的操作已經執行落地。
    • 該行的刪除版本號大於當前版本或者為空。刪除版本號大於當前版本意味著有一個併發事務將該行刪除了。
  • insert:將新插入的行的建立版本號設定為當前系統的版本號。
  • delete:將要刪除的行的刪除版本號設定為當前系統的版本號。
  • update:不執行原地update,而是轉換成insert + delete。將舊行的刪除版本號設定為當前版本號,並將新行insert同時設定建立版本號為當前版本號

其中,寫操作(insert、delete和update)執行時,需要將系統版本號遞增。

​ 由於舊資料並不真正的刪除,所以必須對這些資料進行清理,innodb會開啟一個後臺執行緒執行清理工作,具體的規則是將刪除版本號小於當前系統版本的行刪除,這個過程叫做purge。

通過MVCC很好的實現了事務的隔離性,可以達到repeated read級別,要實現serializable還必須加鎖。

 

MVCC的實現

  1. 為了實現MVCC,innodb對每一行都加上兩個隱含的列,其中一列儲存行被更新的時間,另外一列儲存行被刪除的時間。但是innodb儲存的並不是絕對的時間,而是與時間對應的資料庫系統的版本號。(儲存這兩個額外系統版本號使大多數讀操作可以不加鎖)

  2. 每當一個事務開始的時候,innodb都會給這個事務分配一個遞增的版本號。所以版本號也可以被認為是事務號。

  3. 對於每一個查詢語句,innodb都會把這個查詢語句的版本號同查詢遇到的行的版本號進行對比,然後結合不同的事務等級來決定是否返回該行。

select語句實現

Innodb只查詢版本號早於當前事務版本的資料號(包括等於)。這樣可以確保事務讀取的行要麼是事務開始前已經存在的,要麼是事務自身插入或修改的。

行的刪除版本號,要麼未定義,要麼大於當前事務版本號。這可以確保事務讀取到的行在事務開始之前未被刪除。

insert語句實現

Innodb為新插入的每一行儲存當前系統版本號作為行版本號。

update語句實現

Innodb為插入一行新記錄,儲存當前系統版本號作為行版本號,同時儲存當前系統版本號為原來的行的刪除標識。