一文搞懂InnoDB MVCC機制(轉載)

yahjsk 發佈 2022-05-16T18:08:57.990525+00:00

MVCC是什麼? MVCC是指多版本並發控制。MVCC是在並發訪問資料庫時,通過對數據進行多版本控制,避免因寫鎖而導致讀操作的堵塞,從而很好的優化並發堵塞問題。解決並發問題的通用方案有:(1)對並發訪問的數據添加一把排它鎖,添加鎖之後,其他的讀和寫操作都需等待鎖釋放後才能訪問。

MVCC是什麼?

MVCC是指多版本並發控制。MVCC是在並發訪問資料庫時,通過對數據進行多版本控制,避免因寫鎖而導致讀操作的堵塞,從而很好的優化並發堵塞問題。解決並發問題的通用方案有:

(1)對並發訪問的數據添加一把排它鎖,添加鎖之後,其他的讀和寫操作都需等待鎖釋放後才能訪問。

(2)添加一把共享鎖,讀讀操作不需要等待鎖的釋放,讀寫和寫寫操作需要等待鎖的釋放。

(3)通過對並發數據進行快照備份,從而達到無鎖數據的並發訪問。

通俗的講就是MVCC通過對數據進行多版本保存,根據比較版本號來控制數據是否展示,從而達到讀取數據時無需加鎖就可以實現事務的隔離性。

MVCC的實現原理

​ MVCC的兩個實現核心是undo log一致性視圖,通過undo log來保存多版本的數據,通過一致性視圖來保存當前活躍的事務列表,將兩者結合和制定一定的規則來判斷當前可讀數據。

我們舉個例子來分析下MVCC的具體流程:

undo log是什麼?它在MVCC中啟到什麼作用?

​ innodb在修改資料庫數據記錄之前會先在undo log中記錄回滾日誌,日誌的內容為:執行insert時會對應在undo log中記錄一條delete語句,並且會記錄這個版本的事務id(txid),執行update語句會有一條update語句來使之數據恢復到上個版本。

​ undo log主要用於事務回滾和mvcc獲取不同事務id對應的數據來實現事務隔離。

​ undo log日誌的存儲跟redo log有些區別,undo通過段的形式存儲在共享表空間中,redo log存儲於日誌文件中。

​ undo log的內容變更也會記錄到redo log中,從而實現undo log的持久化。

總結:undo log實現了資料庫快照功能,通過事務id和undo log我們可以找到歷史版本的數據。

一致性視圖是什麼?

​ innodb為每個事務構造了一個數組,用來保存這個事務啟動瞬間,當前正在「活躍」的所有事務ID。「活躍」指的就是,啟動了但還沒提交。簡而言之一致性視圖是個數組,記錄了當前活躍的事務ID,通過這個數據我們可以判斷出來事務執行的先後順序,事務所能讀取的數據版本。

在innodb 中每個SQL語句執行前都會得到一個read_view。副本主要保存了當前資料庫系統中正處於活躍(沒有commit)的事務的ID號,其實簡單的說這個副本中保存的是系統中當前不應該被本事務看到的其他事務id列表。

數組裡面事務ID的最小值記為低水位,當前系統裡面已經創建過的事務ID的最大值加1記為高水位。

這個視圖數組和高水位,就組成了當前事務的一致性視圖(read-view)

一個數據版本,對於一個事務視圖來說,除了自己的更新總是可見以外,有三種情況:

  1. 版本未提交,不可見;
  2. 版本已提交,但是是在視圖創建後提交的,不可見;
  3. 版本已提交,而且是在視圖創建前提交的,可見。

通過上述的概念我們來解下開始的例子:

假設當前有個正在執行事務99,數據行的歷史版本為事務id90(1,1)。

(1)按照事務的開啟時間,分別遞增分配了100,101,102三個事務ID(trx id)

(2)在SQL語句執行之前,事務A生成一致性視圖【99,100】,事務B生成一致性視圖【99,100,101】,事務C生成一致性視圖【99,100,101,102】

(3)SQL語句的執行之前生成undo log,通過undo log可以生成歷史版本數據快照,上圖右側歷史版本數據。

(4)事務A的查詢執行時,當前數據版本為trx id:101,跟一致性視圖【99,100】進行比較,101大於高水位不可見,通過undo log回退到trx id:102版本,102也大於高水位不可見,再回退一個版本到trx id:90,90低於低水位可見,所以事務A讀取到的數據為(1.1)。

轉摘地址:https://zhuanlan.zhihu.com/p/231947511

關鍵字: