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

MySQL 事務深度解析:ACID 特性、隔離級別、鎖機制與最佳實踐

     編輯:MySQL 綜合教學

MySQL 事務深度解析

事務是數據庫區別於文件系統的核心特性。本文從原理到實戰,系統講解 ACID、隔離級別、鎖類型、死鎖處理、Savepoint 以及非事務引擎的替代方案。

一、事務基礎:ACID 特性

特性全稱MySQL/InnoDB 實現機制
AAtomicity(原子性)Undo Log 記錄反操作,Crash 時回滾未提交事務
CConsistency(一致性)外鍵、唯一索引、檢查約束 + 原子性保證
IIsolation(隔離性)MVCC + 行鎖/間隙鎖,四種隔離級別可調
DDurability(持久性)Redo Log (WAL) + innodb_flush_log_at_trx_commit=1 刷盤

二、事務控制語句

-- 顯式事務(推薦)
START TRANSACTION;  -- 或 BEGIN / BEGIN WORK
UPDATE account SET balance = balance - 100 WHERE id = 1;
UPDATE account SET balance = balance + 100 WHERE id = 2;
COMMIT;  -- 提交
-- ROLLBACK;  -- 回滾

-- 隱式事務(autocommit=0)
SET autocommit = 0;
UPDATE ...;
UPDATE ...;
COMMIT;  -- 必須顯式提交

-- 保存點(部分回滾)
SAVEPOINT sp1;
UPDATE ...;
SAVEPOINT sp2;
ROLLBACK TO SAVEPOINT sp1;  -- 回滾到 sp1,sp2 失效
RELEASE SAVEPOINT sp1;      -- 釋放保存點

三、隔離級別與並發異常

MySQL 默認 REPEATABLE READ (RR),通過 MVCC + Next-Key Lock 解決幻讀。

隔離級別髒讀不可重複讀幻讀鎖/ MVCC 行為
READ UNCOMMITTED✅✅✅無鎖,讀取最新版本
READ COMMITTED (RC)❌✅✅每次 SELECT 生成 Read View,僅加記錄鎖
REPEATABLE READ (RR)❌❌❌*事務啟動時生成 Read View,Next-Key Lock 防幻讀
SERIALIZABLE❌❌❌SELECT 自動加共享鎖,退化為單線程

* RR 下通過 Next-Key Lock(記錄鎖+間隙鎖)實質上避免了幻讀,但極端並發仍可能出現「幻影」現象,嚴格串行化需用 SERIALIZABLE。

查看/設置隔離級別

-- 當前會話
SELECT @@transaction_isolation;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

-- 全局(新連接生效)
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;

四、InnoDB 鎖體系全景

1. 按粒度分類

  • 表鎖:LOCK TABLES、DDL、外鍵檢查、全表掃描無索引時。
  • 行鎖:索引命中時。
    • 記錄鎖:鎖定單行記錄。
    • 間隙鎖:鎖定索引間隙,防止幻讀(RR 默認)。
    • Next-Key Lock:記錄鎖 + 間隙鎖,左開右閉區間。
  • 意向鎖:表級,IS(意向共享)、IX(意向排他),協調表鎖與行鎖兼容性。

2. 共享鎖 vs 排他鎖

-- 共享鎖 (S Lock):允許並發讀,阻塞寫
SELECT * FROM t WHERE id = 1 LOCK IN SHARE MODE;

-- 排他鎖 (X Lock):阻塞讀寫
SELECT * FROM t WHERE id = 1 FOR UPDATE;
UPDATE t SET ... WHERE id = 1;  -- 隱式 X 鎖

3. 悲觀鎖 vs 樂觀鎖(應用層模式)

維度悲觀鎖樂觀鎖
適用場景衝突頻繁、寫多讀少衝突稀少、讀多寫少
實現SELECT ... FOR UPDATE版本號/時間戳 + CAS 更新
優點強一致性、簡單無鎖開銷、高併發吞吐
缺點鎖等待、死鎖風險、擴展性差重試邏輯、ABA 問題

五、死鎖檢測與處理

  • InnoDB 內建 Wait-for Graph 死鎖檢測,犧牲權重較小(修改行少)的事務回滾。
  • innodb_lock_wait_timeout(默認 50s)控制等待上限。
  • 應用層捕獲 Error 1213 (ER_LOCK_DEADLOCK) 後重試。

死鎖預防原則

  1. 業務邏輯固定順序訪問表/行(如按 ID 升序)。
  2. 縮短事務持續時間,避免事務中做 RPC/網絡調用。
  3. 適當降低隔離級別(RC 減少間隙鎖)。
  4. 為查詢條件建立合適索引,避免全表掃描升級為表鎖。

六、非事務引擎(MyISAM)替代方案:表鎖

-- 讀鎖(共享)
LOCK TABLES t READ;
SELECT * FROM t;
UNLOCK TABLES;

-- 寫鎖(排他)
LOCK TABLES t WRITE;
UPDATE t SET ...;
UNLOCK TABLES;

缺點:並發性極差,無崩壞恢復能力,已被 InnoDB 完全取代。

七、實戰最佳實踐清單

  1. 核心業務強制使用 InnoDB,建表指定 ENGINE=InnoDB。
  2. 事務邊界在應用層明確控制(Spring @Transactional、Go tx.Begin())。
  3. 單事務 SQL 條數 < 100,執行時間 < 100ms,避免長事務阻塞 Purge、膨脹 Undo Log。
  4. 異常捕獲後必須 Rollback,否則連接池歸還時隱式提交髒數據。
  5. 大批量寫入拆分為小事務,或使用 LOAD DATA 繞過事務開銷。
  6. 監控指標:Innodb_row_lock_waits、Innodb_deadlocks、Trx_rseg_history_len(Undo 積壓)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved