| 級別 | 髒讀 | 不可重複讀 | 幻讀 | InnoDB 預設 |
| READ UNCOMMITTED | Y | Y | Y | |
| READ COMMITTED | N | Y | Y | Oracle/PostgreSQL 預設 |
| REPEATABLE READ | N | N | Y (標準) | InnoDB 預設 |
| SERIALIZABLE | N | N | N | |
InnoDB REPEATABLE READ 獨特行為:無幻讀
標準 RR 允許幻讀,但 InnoDB 通過 Next-Key Locking (記錄鎖 + 間隙鎖) 實現無幻讀,等同 SERIALIZABLE 效果但併發度更高。
實測驗證過程
-- 環境:MySQL 5.0.37, 兩個 Session,隔離級別 RR, autocommit=0
-- Session 1
CREATE TABLE test (i INT) ENGINE=InnoDB;
INSERT INTO test VALUES (1);
-- 未提交
-- Session 2
SELECT * FROM test; -- Empty set (無髒讀)
-- Session 1
COMMIT;
-- Session 2
SELECT * FROM test; -- Empty set (無幻讀!標準 RR 會看到新行)
-- Session 2
COMMIT; -- 或新事務
SELECT * FROM test; -- 現在看到 (1)
MVCC 實現核心
- Undo Log 版本鏈:每行記錄隱藏
DB_TRX_ID (事務 ID)、DB_ROLL_PTR (回滾指針)
- Read View:事務啟動時建立,記錄當前活躍事務 ID 列表
- 可見性判斷:
- 目標版本
trx_id < read_view.min_trx_id → 可見(已提交)
- 目標版本
trx_id > read_view.max_trx_id → 不可見(未來事務)
- 中間:檢查是否在活躍列表 → 在則不可見,不在則可見
- RR vs RC 差異:RR 事務啟動建立 Read View,全程複用;RC 每條 SELECT 重新建立
鎖與隔離級別關係
| 操作 | READ COMMITTED | REPEATABLE READ |
| SELECT (普通) | 無鎖 (MVCC) | 無鎖 (MVCC) |
| SELECT ... LOCK IN SHARE MODE | 記錄鎖 (S) | 記錄鎖 + 間隙鎖 (Next-Key) |
| SELECT ... FOR UPDATE | 記錄鎖 (X) | 記錄鎖 + 間隙鎖 (Next-Key) |
| UPDATE/DELETE (有索引) | 記錄鎖 | Next-Key Lock |
| UPDATE/DELETE (無索引) | 全表記錄鎖 | 全表 Next-Key Lock |
修改隔離級別
-- 全域 (需重連生效)
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 或 my.cnf: transaction-isolation = READ-COMMITTED
-- 會話級 (立即生效)
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 查看
SELECT @@GLOBAL.tx_isolation, @@SESSION.tx_isolation;
選型建議
- RR (預設):大多數業務,無幻讀保證,併發較好
- RC:需見最新提交數據、減少間隙鎖死鎖、Statement-based Replication 相容
- SERIALIZABLE:極少用,嚴格串行化,效能差
- 上一篇文章: SQL Server 字串分割函數實現:自定義函數 getstrcount、getstrofindex、getEPnum 完整代碼
- 下一篇文章: InnoDB 核心參數詳細解析:記憶體、日志、表空間、併發控制與動態調整
Copyright ©
程式碼之家 All Rights Reserved