MySQL/InnoDB 支持四種事務隔離級別,通過 MVCC (多版本並發控制) 與鎖機制實現。隔離級別不僅決定數據可見性,更直接影響**版本鏈維護開銷、鎖競爭、掃描性能、備份一致性**。本文深度剖析各級別性能特徵、實測數據、最佳實踐選型建議。
| 隔離級別 | 核心機制 | MVCC 視圖建立時機 | 鎖行為 | 典型問題 |
|---|---|---|---|---|
| SERIALIZABLE | 全表/範圍共享鎖 (S-Lock) + 間隙鎖 | 無 MVCC,全部加鎖讀 | SELECT 加 S-Lock,嚴重阻塞寫入 | 並發極低、死鎖頻發、幾乎不用 |
| REPEATABLE READ (RR) | 事務啟動時建立 Read View (首次 SELECT) | **事務級** (First SELECT) | 間隙鎖防止幻讀、Next-Key Lock | **默認級別**,長事務導致版本鏈暴增、Purge 阻塞、掃描慢 |
| READ COMMITTED (RC) | 每條語句建立 Read View | **語句級** (Each Statement) | 無間隙鎖 (僅 Row Lock),半一致性讀 | 長 SELECT 仍產生版本,但比 RR 少得多 |
| READ UNCOMMITTED (RU) | 直接讀取最新提交版本 (髒讀) | 無 Read View,讀最新版本 | SELECT 不加鎖、不檢查版本 | 髒讀、不可重複讀、幻讀全有,但掃描最快 |
BEGIN; SELECT ...; SLEEP(300); COMMIT;) 導致 Purge 線程無法清理該 Read View 之前的版本,Undo Log 暴增、History List Length 飆升。mysqldump --single-transaction 隱式開啟 RR 長事務,**大庫備份期間寫入性能崩塌**,不適用高寫入場景。SELECT ... (如報表) 仍會在語句級建立 Read View,阻塞 Purge,導致版本堆積。**需避免長 SELECT 或拆分為小批次**。# 長事務會話
BEGIN;
SELECT AVG(LENGTH(c)) FROM sbtest1;
SELECT SLEEP(300);
COMMIT;
# 並發寫入壓測
sysbench --threads=64 --oltp-table-size=80M --test=update_index.lua run
結果:RR 隔離級別下,寫入 QPS 隨長事務持續**斷崖式下跌**;RC 明顯緩解;RU 無感知。證明長事務在 RR 下對寫入的「輻射性」破壞力。
[mysqld]
transaction_isolation = READ-COMMITTED
binlog_format = ROW -- RC 必須配合 ROW 格式 Binlog,否則主從不一致
理由:絕大多數 Web 業務不需要 RR 的可重複讀語義,RC 大幅降低版本鏈、鎖競爭、死鎖,提升寫入擴展性。
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;,且**嚴禁長事務** (超時自動回滾、監控告警)。SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; 或專用只讀從庫 (延遲容忍)。--single-transaction 大庫備份,改用 xtrabackup 物理熱備 (無長事務、無鎖、可增量)。隔離級別是性能與一致性的桿秤:**RR (默認) 為一致性付出高昂性能代價;RC 是 90%+ 業務的性價比最優解;RU 是特定分析場景的加速器;SERIALIZABLE 是理論構建。** DBA 應將默認調整為 RC、配合 ROW Binlog、嚴控長事務、備份改物理,才能釋放 InnoDB 真實性能。