首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL MVCC 多版本並發控制核心機制深度解析 (InnoDB 實作)

     編輯:MySQL 資料庫相關知識

MVCC (Multi-Version Concurrency Control) 是 InnoDB、PostgreSQL、Oracle 等主流引擎實現高並發的核心技術。它以 **非阻塞讀寫** 取代傳統鎖機制,讓讀操作不加鎖、寫操作僅鎖必要記錄,大幅提升吞吐量。本文聚焦 InnoDB 實作細節。

核心資料結構:隱藏列

每行記錄隱含兩個系統版本號 (System Version Number,遞增整數):

  • DB_TRX_ID (6 bytes):**建立版本** — 建立/最後修改該行的事務 ID。
  • DB_ROLL_PTR (7 bytes):**刪除版本指標** — 指向 Undo Log 中該行的舊版本鏈 (包含刪除標記與前一版本指標)。

關鍵點:不儲存實際時間戳,而是用**事務 ID** 排序版本,避免時間同步問題。

事務視圖一致性

事務啟動時獲取 **Read View** (快照):**當前活躍事務 ID 列表 + 最小活躍 ID + 已提交最大 ID**。
在 **REPEATABLE READ** 隔離級別:首次 SELECT 建立 Read View,事務期間所有 SELECT 共用此視圖** (可重複讀)。
在 **READ COMMITTED**:**每次 SELECT 重新建立 Read View** (不可重複讀,但無幻讀保護較弱)。

四大操作的版本鏈維護

操作版本鏈變更鎖行為
SELECT順著 DB_ROLL_PTR 遍歷 Undo Log 鏈,找符合 Read View 的版本返回**無鎖** (一致性非鎖定讀)
INSERT新行 DB_TRX_ID=當前事務 ID,DB_ROLL_PTR=NULL隱含排他鎖 (X Lock) 於新行
DELETE舊行標記刪除旗標,DB_TRX_ID=當前事務 ID,DB_ROLL_PTR指向 Undo Log 完整舊行X Lock 於被刪行
UPDATE1. 插入新版本行 (新 DB_TRX_ID)
2. 舊行 DB_TRX_ID=當前事務 ID,DB_ROLL_PTR指向 Undo Log 舊版本
X Lock 於舊行 + 新行

可見性判斷演算法 (Read View 檢查)

對某行版本 trx_id:

  1. trx_id < ReadView.min_trx_id → **可見** (在視圖建立前已提交)。
  2. trx_id > ReadView.max_trx_id → **不可見** (在視圖建立後才啟動/提交)。
  3. min_trx_id ≤ trx_id ≤ max_trx_id → 若 trx_id **不在活躍列表** → **可見** (已提交);**在列表** → **不可見** (未提交/正進行中)。
  4. **例外**:若 trx_id == 當前事務 ID → **可見** (看見自己未提交的修改)。

隔離級別相容性

  • READ UNCOMMITTED:不使用 MVCC,直接讀最新版本 (髒讀)。
  • READ COMMITTED:每次 SELECT 新 Read View,支援 MVCC。
  • REPEATABLE READ (InnoDB 預設):單一 Read View,**防止幻讀** (Next-Key Lock 配合)。
  • SERIALIZABLE:退化為鎖模式 (SELECT 加共享鎖),不使用 MVCC。

優勢與代價

優勢代價
讀寫不阻塞,高並發吞吐每行額外 13+ 位元組隱藏列
快照隔離,應用邏輯簡單Undo Log 佔用空間,需定期 Purge
無鎖死風險 (讀操作)版本鏈過長影響查詢效能 (長事務危害)
支援熱備份 (不鎖表)二級索引需回表檢查主鍵版本

長事務危害與監控

  • 長事務持有舊 Read View → Purge 線程無法清理 Undo Log → 版本鏈膨脹 → 查詢變慢、History list length 暴增、磁碟空間耗盡。
  • 監控:SHOW ENGINE INNODB STATUS 觀察 History list length、TRX_ID 差距;SELECT * FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(TIMEDIFF(NOW(), trx_started)) > 60; 找超過 1 分鐘事務。

GBase 8a / 類 Oracle 實作差異補充

  • GBase 8a 採用 **時間戳 (Timestamp)** 而非事務 ID 作為版本標識,Read View 為 **時間點快照**。
  • 預設隔離級別 **READ COMMITTED**,一致性讀使用 **當前時間戳**;REPEATABLE READ 使用 **首次查詢時間戳**。
  • DROP TABLE/ALTER TABLE 期間一致性讀失效 (表重建/刪除),需注意維護窗口。

總結

InnoDB MVCC 以 **隱藏版本列 + Undo Log 版本鏈 + Read View 可見性判斷** 實現無鎖一致性讀。理解其核心流程,有助於排查長事務、幻讀、死鎖、備份一致性等生產疑難雜症,並指導合理的隔離級別選擇與索引設計。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved