MVCC(多版本并發(fā)控制)底層原理總結:
MVCC 是通過維護數據的多個版本來控制并發(fā)訪問的技術扼雏,它使得數據庫能夠支持高并發(fā)事務岂傲,同時保證事務之間的隔離性和一致性扫沼。在 MySQL 的 InnoDB 存儲引擎中叁温,MVCC 是通過 隱藏列、ReadView 快照 和 undo log 來實現的学辱。
1. 關鍵概念:
-
隱藏列(Hidden Columns):為了支持 MVCC 機制乘瓤,InnoDB 在每一行數據中隱藏了兩個額外的列,分別是
DB_TRX_ID
和DB_ROLL_PTR
策泣。這兩個列并不直接暴露給用戶衙傀,但它們對 MVCC 的工作至關重要。DB_TRX_ID
存儲了最近修改該行數據的事務 ID萨咕,而DB_ROLL_PTR
存儲了指向該行數據歷史版本的指針统抬。 - ReadView 快照:為了支持事務隔離級別(如“讀已提交”或“可重復讀”),InnoDB 會在每個查詢操作時創(chuàng)建一個 ReadView 快照危队。該快照存儲了當前查詢事務的 ID聪建、所有未提交事務的事務 ID(按升序排列)以及未開始的事務 ID。通過這些信息茫陆,數據庫可以判斷查詢事務能看到哪些數據版本金麸。
- Undo Log(回滾日志):記錄事務對數據的修改操作。當事務修改數據時簿盅,InnoDB 會為該數據生成一個新的版本挥下,舊版本數據會保存在 undo log 中。
2. ReadView 快照內容:
- 當前查詢事務 ID:表示當前正在執(zhí)行查詢的事務 ID桨醋。
- 未提交事務的事務 ID(按升序排列):記錄了當前未提交事務的事務 ID棚瘟,從最小到最大排序。
- 未開始的事務 ID:記錄那些尚未開始的事務 ID喜最。
3. Undo Log 數據讀取邏輯:
當執(zhí)行查詢操作時解取,InnoDB 會根據當前事務的 ReadView 快照信息來判斷能讀取到哪些數據版本。這一過程通過以下幾個步驟實現:
當前查詢事務 ID = Undo Log 里的事務 ID:如果數據的事務 ID 與當前查詢事務的 ID 匹配返顺,說明該數據是當前事務修改的,當前事務可讀取該數據蔓肯。
Undo Log 事務 ID < 未提交事務的最小事務 ID:如果 Undo Log 中的事務 ID 小于未提交事務的最小事務 ID遂鹊,說明該數據是在當前查詢事務開始之前就已經提交的,因此該數據可被讀取蔗包。
Undo Log 事務 ID > 未開始事務的最大事務 ID:如果 Undo Log 中的事務 ID 大于未開始事務的最大事務 ID秉扑,說明該數據是在查詢事務開始之后的并發(fā)事務中進行修改的,當前事務不能讀取此數據。此時舟陆,需要根據 Undo Log 的指針查找下一條數據误澳。
Undo Log 事務 ID 在未提交事務的最小事務 ID 和最大事務 ID 之間:如果 Undo Log 中的事務 ID 位于未提交事務的最小和最大事務 ID 之間,說明該數據是在并發(fā)的未提交事務中修改的秦躯,當前查詢事務不能讀取此數據忆谓。此時,查詢會再次進行上述判斷踱承,直到找到符合可讀條件的數據倡缠。
4. 讀已提交隔離級別的處理:
- 在 讀已提交 隔離級別下,每次查詢的時候都會創(chuàng)建 ReadView 快照茎活,根據這個快照去 Undo Log 里邊找到數據昙沦,查找到符合條件的最新版本數據。
- 在執(zhí)行查詢時载荔,如果數據修改是未提交事務所做的盾饮,查詢將跳過該數據,直到找到符合條件的數據懒熙。
5. 可重復讀隔離級別的處理:
- 在 可重復讀 隔離級別下丘损,創(chuàng)建 ReadView 快照只會在第一次讀取時進行,后續(xù)的查詢會使用相同的 ReadView 快照煌珊。因為可重復讀第一次讀的數據和之后讀的數據一致号俐,所以只需在第一次讀的時候創(chuàng)建快照。
- 由于同一個快照被多次復用定庵,事務中的讀取操作可以獲得一致的數據版本吏饿,避免了“不可重復讀”的問題。
6. 隱藏列的作用:
DB_TRX_ID
:每一行數據中都會有一個DB_TRX_ID
列蔬浙,它記錄了最后修改該行數據的事務 ID猪落。當查詢需要檢查某行數據時,InnoDB 會根據DB_TRX_ID
來判斷該行數據是否是當前事務能夠讀取的畴博。如果該行的事務 ID 比當前查詢事務的事務 ID 早(即該數據在查詢開始時已提交)笨忌,則該數據對查詢事務可見。DB_ROLL_PTR
:該列指向了該行數據歷史版本的 Undo Log 指針俱病。如果查詢的數據版本不可見官疲,InnoDB 會根據DB_ROLL_PTR
查找該數據的歷史版本,繼續(xù)查找直到找到一個符合條件的可見數據版本亮隙。
7. 總結:
- MVCC通過 隱藏列途凫、ReadView 快照 和 Undo Log 來實現數據的并發(fā)控制,保證高并發(fā)環(huán)境下的數據一致性和事務隔離性溢吻。
- 讀已提交和可重復讀的隔離級別分別通過每次查詢創(chuàng)建 ReadView 快照(讀已提交)或僅在首次讀取時創(chuàng)建快照(可重復讀)來控制數據的可見性维费。
- 通過比較 Undo Log 中的事務 ID 與當前 ReadView 快照中的信息,InnoDB 判斷一個數據版本是否可見,從而保證數據的隔離性犀盟。