首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 事務隔離級別、鎖機制與封鎖協議深度解析:從原理到實戰

     編輯:MySQL 綜合教學

MySQL 事務隔離級別、鎖機制與封鎖協議深度解析:從原理到實戰

數據庫並發控制是後端工程師進階必修課。本文從並發異常現象切入,層層遞進講解三級封鎖協議、四大隔離級別、MVCC 實現、鎖類型與兼容矩陣、兩段鎖協議、死鎖檢測與最佳實踐,幫助你建立完整的並發控制知識體系。

一、並發操作引發的五類異常

異常類型現象描述本質
髒讀A 讀取 B 未提交的修改,B 回滾導致 A 數據非法讀取未提交數據
不可重複讀A 兩次讀取同一行,中間 B 修改並提交,結果不一致讀取已提交的修改/刪除
幻讀A 兩次範圍查詢,中間 B 插入新行滿足條件,結果集變化讀取已提交的新增
第一類丟失更新A 回滾覆蓋 B 已提交的修改回滾覆蓋提交數據
第二類丟失更新A 提交覆蓋 B 已提交的修改提交覆蓋提交數據

Oracle 默認 Read Committed 通過多版本機制天然避免髒讀;MySQL InnoDB 依賴 MVCC + 鎖解決上述問題。

二、三級封鎖協議(理論基石)

  1. 一級:修改前加 X 鎖,事務結束才釋放 → 解決丟失更新,保證可恢復性
  2. 二級:一級 + 讀取前加 S 鎖,讀完即釋放 → 進一步解決髒讀
  3. 三級:一級 + 讀取前加 S 鎖,事務結束才釋放 → 解決不可重複讀

注意:三級封鎖協議仍無法解決幻讀(需表級鎖或謂詞鎖)。

三、四大事務隔離級別(SQL-92 標準)

隔離級別髒讀不可重複讀幻讀並發性能MySQL 默認
READ UNCOMMITTED✅ 可能✅ 可能✅ 可能最高否
READ COMMITTED❌ 不會✅ 可能✅ 可能高Oracle/SQL Server 默認
REPEATABLE READ❌ 不會❌ 不會✅ 可能中MySQL InnoDB 默認
SERIALIZABLE❌ 不會❌ 不會❌ 不會最低否

四、MySQL InnoDB 各級別實現細節

READ UNCOMMITTED

  • 僅遵循一級封鎖協議
  • 修改加 X 鎖,讀不加鎖,直接讀最新版本(含未提交)
  • 極少用於生產

READ COMMITTED

  • 遵循二級封鎖協議
  • 讀加 S 鎖,讀完即釋放(或 MVCC 讀已提交版本)
  • 每次 SELECT 都生成新 Read View,故同一事務多次查詢可能見到不同提交數據 → 不可重複讀
  • InnoDB 實際通過 MVCC 實現非阻塞讀:讀取 Undo Log 中最近提交版本

REPEATABLE READ (RR) —— MySQL 默認

  • 事務啟動時刻建立 Read View,後續所有 SELECT 共用該視圖
  • 只能看到事務開始前已提交的數據 + 自己修改的數據
  • 解決不可重複讀,但無法完全解決幻讀:
    • 快照讀(普通 SELECT)不加鎖,新插入行不會被看到 → 幻讀不發生
    • 當前讀(SELECT ... LOCK IN SHARE MODE / FOR UPDATE、UPDATE/DELETE)加記錄鎖/間隙鎖/Next-Key Lock,防止幻讀
  • 間隙鎖 + Next-Key Lock 是 RR 級別防幻讀的關鍵

SERIALIZABLE

  • 遵循三級封鎖協議
  • 所有 SELECT 隱式加 S 鎖,完全串行化
  • 並發性能極差,極少使用

五、MVCC(多版本並發控制)核心機制

  1. 隱式列:每行含 DB_TRX_ID(最後修改事務 ID)、DB_ROLL_PTR(回滾指針)
  2. Undo Log:記錄舊版本,構成版本鏈
  3. Read View:包含 m_ids(活躍事務 ID 列表)、min_trx_id、max_trx_id、creator_trx_id
  4. 可見性判斷:遍歷版本鏈,找第一個滿足 trx_id < min_trx_id 或 trx_id == creator_trx_id 的版本

RR 級別:事務開始時創建 Read View,全程復用。
RC 級別:每次 SELECT 重新創建 Read View。

六、InnoDB 鎖類型與兼容矩陣

鎖類型粒度兼容性典型場景
記錄鎖單行X-X 互斥,S-S 兼容,S-X 互斥主鍵/唯一索引等值查詢 + FOR UPDATE
間隙鎖區間G-G 兼容,G-X 互斥範圍查詢防幻讀
Next-Key Lock記錄+間隙同記錄鎖RR 級別當前讀默認加鎖
插入意向鎖間隙與 G 鎖衝突INSERT 時自動獲取
表鎖整表意向鎖 (IS/IX) 配合DDL、無索引更新、SERIALIZABLE

意向鎖:IS/IX 表示事務「意圖」在表中加 S/X 鎖,僅用於表級鎖與行級鎖兼容性快速判斷。

七、兩段鎖協議 (2PL)

  • 擴展階段:只能加鎖,不能釋放鎖
  • 收縮階段:只能釋放鎖,不能加鎖
  • 所有事務遵循 2PL ⇒ 調度結果可串行化
  • InnoDB 隱式遵循 2PL:事務中首次加鎖開始擴展,COMMIT/ROLLBACK 時一次性釋放所有鎖

八、死鎖檢測與處理

  • InnoDB 內置 Wait-for Graph 死鎖檢測,定期掃描
  • 發現死鎖選擇「代價最小」事務回滾(通常是修改行數少的)
  • innodb_deadlock_detect = ON(默認)
  • 應用層捕獲 ERROR 1213 (HY000): Deadlock found 重試

九、實戰最佳實踐

  1. 默認使用 RR 級別,核心業務評估是否需 RC(減少間隙鎖衝突)
  2. 所有查詢盡可能走索引,避免無索引更新退化為表鎖
  3. 按固定順序訪問多表/多行(如按主鍵遞增)防止死鎖
  4. 大事務拆小、縮短持鎖時間
  5. 長事務監控:SELECT * FROM sys.innodb_lock_waits / information_schema.innodb_trx
  6. 只讀事務顯式聲明 SET TRANSACTION READ ONLY 或連接參數 readOnly=true,InnoDB 可優化分配 Read View
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved