經典轉賬場景:A 轉 500 給 B。操作序列:扣款 → 入賬。若扣款後系統崩潰,A 損失 500,B 未收款。**事務確保:要麼全成功,要麼全失敗**。
| 特性 | 英文 | 核心含義 | InnoDB 實現機制 |
|---|---|---|---|
| 原子性 | Atomicity | 事務不可分割,全做或全不做 | Undo Log 回滾 |
| 一致性 | Consistency | 事務前後數據庫完整性約束保持 | 原子性+隔離性+持久性+約束檢查 |
| 隔離性 | Isolation | 併發事務互不干擾 | 鎖 + MVCC |
| 持久性 | Durability | 提交後永久生效,抗崩潰 | Redo Log (WAL) |
| 級別 | 髒讀 | 不可重復讀 | 幻讀 | InnoDB 默認 | 實現機制 |
|---|---|---|---|---|---|
| READ UNCOMMITTED | ✅ | ✅ | ✅ | 否 | 無鎖,直接讀最新 |
| READ COMMITTED | ❌ | ✅ | ✅ | 否 (Oracle 默認) | Read View 每語句重建 |
| REPEATABLE READ | ❌ | ❌ | ❌* | ✅ (MySQL 默認) | Read View 事務首次建立 + Gap Lock |
| SERIALIZABLE | ❌ | ❌ | ❌ | 否 | 讀加共享鎖,寫加排他鎖,串行執行 |
* InnoDB RR 級別通過 **Gap Lock(間隙鎖)+ Next-Key Lock** 解決幻讀,實際達到串行化效果但保留並發性能。
-- 每行隱含 DB_TRX_ID -- 最後修改事務 ID DB_ROLL_PTR -- 指向 Undo Log 版本鏈 DB_ROW_ID -- 無主鍵時生成單調遞增 ID
Read View 包含: - m_ids: 活躍事務 ID 列表 - min_trx_id: 最小活躍事務 ID - max_trx_id: 最大已分配事務 ID + 1 - creator_trx_id: 創建該 Read View 的事務 ID 可見性判斷: 1. trx_id < min_trx_id → 可見 (已提交) 2. trx_id >= max_trx_id → 不可見 (未來事務) 3. min_trx_id <= trx_id < max_trx_id: - trx_id 在 m_ids 中 → 不可見 (活躍中) - trx_id 不在 m_ids 中 → 可見 (已提交)
1. START TRANSACTION 2. 修改記錄 → 寫 Undo Log (記錄舊值) → 寫 Redo Log (記錄新值) → 更新內存頁 3. COMMIT 前:將 Redo Log 刷盤 (fsync) -- 關鍵持久化點 4. COMMIT:標記事務提交,釋放鎖 5. 後台:將內存髒頁刷盤 (Checkpoint)
模型三角色: AP (Application) : 發起全局事務,定義邊界 RM (Resource Manager) : 每個 MySQL 實例,管理本地資源 TM (Transaction Manager): 協調器,如 Atomikos, Seata, Narayana 流程: Phase 1 (Prepare): TM 發送 XA PREPARE 給所有 RM RM 執行本地事務至 Prepare 狀態,寫 Redo Log 含 PREPARE 標記,回覆 Ready Phase 2 (Commit/Rollback): 若所有 Ready → TM 發 XA COMMIT → RM 提交本地事務 若任一失敗 → TM 發 XA ROLLBACK → 所有 RM 回滾 風險:TM 單點故障、網絡分區導致阻塞、Heuristic 決定(人工干預)
InnoDB 事務是 **鎖(隔離)+ MVCC(讀不阻寫)+ Redo Log(持久)+ Undo Log(原子+MVCC)** 的精密協作。理解底層原理,才能在死鎖分析、長事務治理、分布式一致性方案選型中做出正確決策。