萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL InnoDB 事務與鎖機制深度解析:ACID、隔離級別、鎖類型與實戰驗證

事務四大特性(ACID)

特性含義
原子性事務內所有操作要麼全做,要麼全不做
一致性事務前後數據庫從一個一致性狀態轉換到另一個
隔離性併發事務互不干擾,內部操作對其他事務不可見
持久性提交後的修改永久生效,不受後續故障影響

InnoDB 鎖類型與加鎖語句

語句鎖類型兼容性備註
SELECT ... LOCK IN SHARE MODE共享鎖 (S)兼容 S,阻塞 X讀取並防止他人修改
SELECT ... FOR UPDATE排他鎖 (X)阻塞 S/X讀取並防止他人讀寫
INSERT/UPDATE/DELETE排他鎖 (X)阻塞 S/X隱式加鎖
範圍查詢間隙鎖 / Next-Key Lock阻塞插入防止幻讀,鎖定不存在的區間

⚠️ 具體加鎖行為還受 事務隔離級別 影響

四大隔離級別對比

級別髒讀不可重複讀幻讀備註
READ UNCOMMITTED✅ 可能✅ 可能✅ 可能性能最好,極少用
READ COMMITTED❌✅ 可能✅ 可能Oracle 默認,RC
REPEATABLE READ❌❌❌ (MVCC+Gap Lock)InnoDB 默認,RR
SERIALIZABLE❌❌❌SELECT 自動加 S 鎖,串行化

實戰驗證:同一行在不同隔離級別下的可見性

測試表 account(id PK, vaccount_id, gmt_create),10 萬行數據。

READ UNCOMMITTED:可見未提交修改(髒讀)

T1: START TRANSACTION; SELECT vaccount_id FROM account WHERE id=1001; -- caimao101510
T2: START TRANSACTION; UPDATE account SET vaccount_id='uncommitted' WHERE id=1001;
T1: SELECT vaccount_id FROM account WHERE id=1001; -- uncommitted (髒讀)
T2: ROLLBACK;
T1: SELECT vaccount_id FROM account WHERE id=1001; -- caimao101510

READ COMMITTED:不可重複讀

T1: START TRANSACTION; SELECT ...; -- caimao101510
T2: START TRANSACTION; UPDATE ... SET vaccount_id='uncommitted'; COMMIT;
T1: SELECT ...; -- uncommitted (前後兩次讀不一致)

REPEATABLE READ:可重複讀(InnoDB 默認)

T1: START TRANSACTION; SELECT ...; -- caimao101510
T2: START TRANSACTION; UPDATE ... SET vaccount_id='uncommitted'; COMMIT;
T1: SELECT ...; -- caimao101510 (仍舊讀到舊值,MVCC 快照)

最佳實踐建議

  1. 默認使用 REPEATABLE READ,滿足絕多數業務一致性需求
  2. 長事務、高併發場景評估 READ COMMITTED + 悲觀鎖/樂觀鎖
  3. 明確需要串行化時才用 SERIALIZABLE 或應用層分布式鎖
  4. 善用 SELECT ... FOR UPDATE / LOCK IN SHARE MODE 顯式控制併發
  5. 監控 INNODB_LOCK_WAITS、INNODB_TRX 定位死鎖/長事務
copyright © 萬盛學電腦網 all rights reserved