MySQL 理解事務隔離級別
在SQL標準中定義了四種隔離級別,每一種級別都規定了一個事務中所做的修改,哪些在事務內和事務間是可見的,哪些是不可見,較低的隔離級別通常可以執行更高的併發,系統的開銷也更低
事務的ACID
-
原子性(atomicity)
一個事務必須視為一個不可分割的最小工作單元,整個事務的所有操作要麼全部提交成功,要麼全部回滾
-
一致性(consistency)
資料庫總是從一個一致性狀態轉換到另一個一致性狀態。
-
隔離性(isolation)
通常來說,一個事務所作的修改在最終提交以前,對其他事務是不可見的,在討論隔離級別的時候,會理解為什麼說是 "通常來說" 是不可見的
-
永續性(durability)
一旦事務提交,則所做的修改就會永久的儲存到資料庫中
隔離級別
1.READ UNCOMMITTED (未提交讀)
- 即在該級別,事務中的對資料的修改,即使沒有提交,對其他事務也是可見的。這種情況被稱為髒讀(Dirty Read),這個級別會導致很多問題,而且效能相比其他級別不會好太多,實際很少使用。
2.READ COMMITTED (提交讀)
- 大多資料庫的預設隔離級別(但MySQL不是),該級別解決了髒讀的問題。但是事務中會讀到其他事務已提交的資料,無法保證讀一致性,會造成不可重複讀的問題。如下事務的兩次讀取是不一致的

READ COMMITTED
3.REPEATABLE READ (可重複讀)
- 該隔離級別,解決了髒讀,不可重複讀。InnoDB 使用 MVCC (多版本併發控制下文會講到) 保證了事務中的 讀一致性 。但還是會出現一個 幻讀 的情況
- 如下圖(左為事務A,右為事務B)
事務執行這樣的邏輯:查詢是否有某條記錄,如果不存在則新增。
id="1" select * from where id = "1"

REPEATABLE READ
- RR 級別下如何防止幻讀
# 用 X鎖 SELECT i` FROM `users` WHERE `id` = "1" FOR UPDATE;
如果 id = 1 的記錄存在則會被加行(X)鎖,如果不存在,則會加 next-lock key / gap 鎖(範圍行鎖),即記錄存在與否,mysql 都會對記錄應該對應的索引加鎖,其他事務是無法再獲得做操作的。

REPEATABLE READ 解決幻讀
4.SERIALIZABLE (序列化)
在該隔離級別下,讀取的每一行都會被新增鎖(個人理解是讀鎖和gap鎖),導致大量的超時和鎖爭用問題,實際應用中很少使用,只有在非常需要確保資料一致性且可以接受沒有併發的情況下,才考慮該級別。
- 在 SERIALIZABLE 級別下再執行一下 上述的demo
- 可以看到步驟2的 insert 被阻塞了,上述 "幻讀" 的情況

SERIALIZABLE
MVCC
MVCC 是什麼
- MVVC (Multi-Version Concurrency Control, 多版本併發控制),在InnoDB引擎下,MVCC是為了實現事務的隔離性,通過版本號,避免同一資料在不同事務間的競爭,你可以把它當成基於多版本號的一種樂觀鎖, 讀不加鎖,讀寫不衝突
MVCC 實現機制
-
InnoDB在每行資料都增加兩個隱藏欄位,一個記錄 建立的版本號 ,一個記錄 刪除的版本號 。
-
在MVVC 中,為了保證資料操作在多執行緒過程中,保證事務隔離的機制,降低鎖競爭的壓力,保證較高的併發量。 在每開啟一個事務時,會生成一個事務的版本號 ,被操作的資料會生成一條新的資料行(臨時),但是在提交前對其他事務是不可見的,對於資料的更新(包括增刪改)操作成功,會將這個版本號更新到資料的行中,事務提交成功,將新的版本號更新到此資料行中,這樣保證了每個事務操作的資料,都是互不影響的,也不存在鎖的問題。
MVVC下的CRUD (REPEATABLE READ下)
-
SELECT:
InnoDB 查詢的每行資料必須滿足以下兩點
1、InnoDB必須找到一個行的版本,它至少要和事務的版本一樣老(即它的版本號不大於事務的版本號)。這保證了不管是事務開始之前,或者事務建立時,或者修改了這行資料的時候,這行資料是存在的。
2、這行資料的刪除版本必須是未定義的或者比事務版本要大。這可以保證在事務開始之前這行資料沒有被刪除。
符合這兩個條件的行可能會被當作查詢結果而返回。
-
INSERT:
InnoDB為這個新行記錄當前的系統版本號。
-
DELETE:
InnoDB將當前的系統版本號設定為這一行的刪除ID。
-
UPDATE:
InnoDB會寫一個這行資料的新拷貝,這個拷貝的版本為當前的系統版本號。它同時也會將這個版本號寫到舊行的刪除版本里。
參考
- MySQL之MVVC簡介
- mysql 幻讀的詳解、例項及解決辦法
- 《高效能MySQL 第三版》