MySql MVCC是如何實現的-事務隔離級別?
事務就是要保證一組資料庫操作,要麼全部成功,要麼全部失敗。
在MySql中,事務支援是在引擎層實現的,但是隻有InnoDB支援事務,MyISAM是不支援的。
事務具有原子性,一致性,隔離性,永續性,這裡我們要談的就是隔離性。
MySql標準的事務隔離級別包括:
讀未提交(read uncomminted):一個事務還沒有提交時,它做的變更就能被被的事務看到。
讀提交(read commited):一個事務提交後,它做的變更才會被其他事務看到。
可重複讀(repeatable read):一個事務執行過程中看到的資料,總是跟這個事務在啟動時看到的資料是一致的。
序列化(serializable)
事務隔離級別 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|
讀未提交 | 是 | 是 | 是 |
不可重複讀 | 否 | 是 | 是 |
可重複讀 | 否 | 否 | 是 |
序列化 | 否 | 否 | 否 |
1.檢視MySql預設的隔離級別,可見MySql預設可重複讀。從上圖我們可以看到,不管是什麼隔離級別,都會存在一些問題,並且隔離的越嚴實,執行效率就會越低。比如:序列化,所以很多時候我們只是在效率和隔離之間找一個平衡點。
MySql5.7以前的版本:show variables like 'tx_isolation';
MySql5.7(包含)以後的版本:show variables like 'transaction_isolation';
mysql> show variables like 'tx_isolation';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)
舉例說明:
事務A | 事務B |
---|---|
1啟動事務 | |
2.查詢得到值V0 | 3啟動事務 |
4.查詢得到值V0 | |
5.將V0改為V0+1 | |
6.查詢得到值V1 | |
7.提交事務B | |
8.查詢得到值V2 | |
9.提交事務A | |
10.查詢得到值V3 |
1.讀未提交
- 將會話的隔離級別設定為讀未提交,終端1和終端2一起設定
set session transaction isolation level read uncommitted;
- 按照上述表格中的順序,依次執行,得到V0=1,V1=2,V2=2,V3=2
注意步驟6直接讀到了步驟5中修改的值,此時事務B實際還未提交,這就是讀未提交(read uncommited),事務級別讀未提交存在髒讀的問題,比如此用例中如果事務B做了回滾,那麼事務A在第4步驟查詢得到的值就是不正確的,這就是所謂的髒讀
2.讀提交
- 將會話的隔離級別設定為讀提交,終端1和終端2一起設定
set session transaction isolation level read committed;
- 按照上述表格中的順序,依次執行,得到V0=2,V1=2,V2=3,V3=3
注意步驟6沒有讀到步驟5中修改的值,步驟7,事務B提交之後,步驟8讀到了步驟5修改的值,這就是讀提交(read commited),事務級別讀提交存在不可重複讀的問題,比如此用例中,同一個事務,在不同的階段讀同一行資料讀到了不同的值,這就是所謂的不可重複讀,解決不可重複讀的方法是加行鎖,事務A在執行未提交的時候,事務B無法修改資料,即可避免
3.可重複讀
- 將會話的隔離級別設定為可重複讀,終端1和終端2一起設定
set session transaction isolation level repeatable read;
- 按照上述表格中的順序,依次執行,得到V0=3,V1=3,V2=3,V3=4
注意步驟6沒有讀到步驟5中更改的值,步驟7事務B提交之後,步驟8依然沒有讀到步驟5中更改的值,直到事務A也提交之後才讀到事務B更改的值,這就是可重複讀(repeatable read)
- 事務級別可重複讀存在幻讀的問題
事務A | 事務B |
---|---|
1啟動事務 | |
2查詢V0 | |
3插入 | |
4查詢V1 | |
5提交事務 | |
6查詢V2 | |
7更新 | |
8查詢V3 |
- 按照上述表格的順序,依次執行,V0=V1=V2=5行,V3=6行,也就是在事務A中查到事務B插入的資料,這就是所謂的幻讀,解決幻讀的方法是加表鎖,事務A在執行未提交的時候,事務B無法插入資料,即可避免
4.序列化
- 將會話的隔離級別設定為序列化,終端1和終端2一起設定
set session transaction isolation level serializable;
事務A | 事務B |
---|---|
1啟動事務 | |
2啟動事務 | |
3插入資料 | |
4查詢資料 | |
5提交事務 | |
6查詢資料 |
按照上述表格的順序,依次執行,步驟3插入資料,但是未提交的時候,步驟4出現了獲取鎖超時的情況,這就是序列化(serializable
),同一行資料不允許併發執行,在寫時,讀必須等待。