1. 程式人生 > 其它 >MVCC多版本併發控制機制

MVCC多版本併發控制機制

​ Mysql在可重複讀隔離級別下如何保證事務較高的隔離性,這個隔離性就是靠MVCC(Multi-Version Concurrency Control)機制來保證的,對一行資料的讀和寫兩個操作預設是不會通過加鎖互斥來保證隔離性,避免了頻繁加鎖互斥,而在序列化隔離級別為了保證較高的隔離性是通過將所有操
作加鎖互斥來實現的。
​ Mysql在讀已提交和可重複讀隔離級別下都實現了MVCC機制。

undo日誌版本鏈與read view機制詳解

​ undo日誌版本鏈是指一行資料被多個事務依次修改過後,在每個事務修改完後,Mysql會保留修改前的資料undo回滾
日誌,並且用兩個隱藏欄位trx_id和roll_pointer把這些undo日誌串聯起來形成一個歷史記錄版本鏈(見下圖,需參考視
頻裡的例子理解) 。

​ 在可重複讀隔離級別,當事務開啟,執行任何查詢sql時會生成當前事務的一致性檢視read-view,該檢視在事務結束
之前都不會變化(如果是讀已提交隔離級別在每次執行查詢sql時都會重新生成),這個檢視由執行查詢時所有未提交事
務id陣列(數組裡最小的id為min_id)和已建立的最大事務id(max_id)組成,事務裡的任何sql查詢結果需要從對應
版本鏈裡的最新資料開始逐條跟read-view做比對從而得到最終的快照結果。

版本鏈比對規則:

  1. 如果 row 的 trx_id 落在綠色部分( trx_id<min_id ),表示這個版本是已提交的事務生成的,這個資料是可見的;
  2. 如果 row 的 trx_id 落在紅色部分( trx_id>max_id ),表示這個版本是由將來啟動的事務生成的,是不可見的(若
    row 的 trx_id 就是當前自己的事務是可見的);
  3. 如果 row 的 trx_id 落在黃色部分(min_id <=trx_id<= max_id),那就包括兩種情況
    1. 若 row 的 trx_id 在檢視陣列中,表示這個版本是由還沒提交的事務生成的,不可見(若 row 的 trx_id 就是當前自己的事務是可見的);
    2. 若 row 的 trx_id 不在檢視陣列中,表示這個版本是已經提交了的事務生成的,可見。
注意:
    對於刪除的情況可以認為是update的特殊情況,會將版本鏈上最新的資料複製一份,然後將trx_id修改成刪除操作的
trx_id,同時在該條記錄的頭資訊(record header)裡的(deleted_flag)標記位寫上true,來表示當前記錄已經被
刪除,在查詢時按照上面的規則查到對應的記錄如果delete_flag標記位為true,意味著記錄已被刪除,則不返回數
據。
    begin/start transaction 命令並不是一個事務的起點,在執行到它們之後的第一個修改操作InnoDB表的語句,
事務才真正啟動,才會向mysql申請事務id,mysql內部是嚴格按照事務的啟動順序來分配事務id的。

總結

​ MVCC機制的實現就是通過read-view機制與undo版本鏈比對機制,使得不同的事務會根據資料版本鏈對比規則讀取
同一條資料在版本鏈上的不同版本資料