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

MySQL 事務隔離級別深度解析:鎖機制、MVCC、髒讀/不可重複讀/幻讀實戰演示

     編輯:MySQL 綜合教學

MySQL 事務隔離級別深度解析

一、鎖類型與粒度

鎖類型特點適用引擎
表鎖開銷最小、並發最低、鎖定整張表MyISAM、DDL 操作
行鎖開銷最大、並發最高、僅鎖相關行InnoDB、Falcon
行鎖僅在存儲引擎層實現,MySQL Server 層感知不到;InnoDB 預設行鎖,支援間隙鎖、Next-Key Lock 解決幻讀。

二、ACID 原則與銀行轉賬示例

BEGIN;
SELECT balance FROM checking WHERE customer_id = 10233276;
UPDATE checking SET balance = balance - 200 WHERE customer_id = 10233276;
UPDATE savings  SET balance = balance + 200 WHERE customer_id = 10233276;
COMMIT;
  • 原子性:要麼全成功要麼全回滾
  • 一致性:轉賬前後總金額不變
  • 隔離性:A 未提交前,B 查詢看到舊餘額
  • 持久性:Commit 後掉電不丟數據

三、五大併發異常現象

異常描述例子
丟失更新回滾覆蓋他人已提交更新A提交→B更新→B回滾→A更新丟失
髒讀讀到未提交數據B更新未提交→A讀到→B回滾→A得髒數據
不可重複讀同一事務兩次讀同行,結果不同A讀→B更新提交→A再讀→值變了
覆蓋更新不可重複讀特例A更新→B更新→A發現自己更新被覆蓋
幻讀同一事務兩次範圍查詢,行數不同A查範圍→B插入新行→A再查→多出行

四、四大隔離級別對比

隔離級別髒讀不可重複讀幻讀備註
READ UNCOMMITTED可能可能可能無共享鎖,性能最高但最不安全
READ COMMITTED不可能可能可能讀取瞬間加共享鎖,讀完即釋放(Oracle 預設)
REPEATABLE READ不可能不可能可能InnoDB 預設,MVCC 快照讀解決不可重複讀
SERIALIZABLE不可能不可能不可能全表共享鎖,串行化,並發極低

五、實戰演示:RR 隔離級別下的幻讀、RC 下的不可重複讀、RU 下的髒讀

準備:建表與數據

CREATE TABLE users (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(32), age TINYINT,
  KEY idx_age (age)
) ENGINE=InnoDB;

INSERT INTO users VALUES
(1,'Bob',27),(2,'Mike',7),(3,'Tony',40),(4,'Bill',21),(5,'Mark',18);

1. 幻讀

SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- 事務1
BEGIN;
SELECT * FROM users WHERE age BETWEEN 10 AND 30;  -- 返回 Bob, Mike, Bill, Mark
-- 事務2
INSERT INTO users VALUES (6,'New',25); COMMIT;
-- 事務1 再次查詢
SELECT * FROM users WHERE age BETWEEN 10 AND 30;  -- RR 下仍只見 4 行,無幻讀(靠 Gap Lock)

2. 不可重複讀

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 事務1
BEGIN;
SELECT * FROM users WHERE id = 1;  -- age=27
-- 事務2
UPDATE users SET age = 21 WHERE id = 1; COMMIT;
-- 事務1 再次查詢
SELECT * FROM users WHERE id = 1;  -- age=21,發生不可重複讀

3. 髒讀

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
-- 事務1
BEGIN;
SELECT * FROM users WHERE id = 1;
-- 事務2
UPDATE users SET age = 21 WHERE id = 1;  -- 未提交
-- 事務1 再次查詢
SELECT * FROM users WHERE id = 1;  -- 讀到 age=21(髒數據)
-- 事務2 ROLLBACK; 事務1 讀到的數據已失效

六、InnoDB MVCC 實現細節

  • 每行隱藏 DB_TRX_ID(創建版本)、DB_ROLL_PTR(回滾指鏈)
  • RR 下:SELECT 讀取「創建版本 ≤ 當前事務版本 且 (刪除版本為空 OR > 當前版本)」的行 → 快照讀,不加鎖
  • LOCK IN SHARE MODE / FOR UPDATE / DML → 當前讀,加 S/X 鎖,讀最新版本

七、binlog 格式與隔離級別的關係

  • STATEMENT:需 SERIALIZABLE 保證主備一致
  • ROW / MIXED:READ COMMITTED 以上即可,推薦生產用 ROW + READ COMMITTED 平衡效能與一致性

八、總結

MySQL InnoDB 預設 RR + MVCC 解決不可重複讀,配合 Next-Key Lock 緩解幻讀;高併發業務常用 RC + ROW binlog 提升並發;極少數強一致場景用 Serializable。理解五大異常、四大級別、MVCC 可見性判斷、鎖類型,是調優與排查併發 Bug 的核心基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved