資料庫系列:MySQL慢查詢分析和效能最佳化
資料庫系列:MySQL索引最佳化總結(綜合版)
資料庫系列:高併發下的資料欄位變更
資料庫系列:覆蓋索引和規避回表
資料庫系列:資料庫高可用及無損擴容
資料庫系列:使用高區分度索引列提升效能
資料庫系列:字首索引和索引長度的取捨
資料庫系列:MySQL引擎MyISAM和InnoDB的比較
資料庫系列:InnoDB下實現高併發控制
資料庫系列:事務的4種隔離級別
1 介紹
上一篇,我們介紹了 SQL92標準中事務的四種隔離級別,並討論了每種隔離級別下 髒讀、不可重複讀、幻讀 問題是否可以解決:
隔離級別 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|
讀未提交:Read Uncommitted | ✔ | ✔ | × |
讀已提交:Read Committed | × | ✔ | × |
可重複讀:Repeatable Read | × | × | ✔ |
序列化:Serializable | × | × | × |
在 讀已提交(Read Committed) 和 可重複讀(Repeatable Read)兩種隔離級別上,資料庫底層採用了快照讀(Snapshot Read)的模式來實現高併發機制。
那RC 和 RR這兩種的隔離級別上的快照讀(Snapshot Read)有什麼區別呢,我們們往下探索?
2 RC 和 RR下快照讀的區別
2.1 啥是快照讀?
MySQL中InnoDB儲存引擎的快照讀(Snapshot Read)是一種讀取資料的方式,它可以在事務開始時建立一個資料快照,這個快照是一致性的,即讀取在事務開始時或特定時間點之前提交的資料。底層原理是MySQL使用多版本併發控制(MVCC)機制來實現快照讀。在MVCC中,每個事務讀取的資料都是根據事務開始時間點或快照時間點確定的。MySQL透過為每一行資料新增版本資訊(如建立版本、刪除版本等),來保留歷史資料的多個版本。透過一種不加鎖一致性讀(Consistent Nonlocking Read)的方式來實現高併發的能力。
2.2 RU和Serializable為啥不採用快照讀?
- Serializable是序列化執行,每個步驟都是順序的,一項事務執行完成才能執行另一項事務,所以沒有MVCC 多版本的必要。
- RU是讀未提交,所有未完成的、未最終提交事務都可以被讀取到,所以任何有變化的資料都會被讀取到,即使是還沒有Commit,也沒有多版本的必要了。
2.3 讀已提交(Read Committed)
- 事務隔離級別的一種,簡稱RC
- 解決了“髒讀”問題,保證讀取到的所有都是已提交事務的,並最終落庫的
- 可能存在“讀幻影行”問題,同一個事務中,前後連續的select可能讀到不同的結果集
2.4 可重複讀(Repeated Read)
- 事務隔離級別的一種,簡稱RR
- 它不僅解決“髒讀”問題,還解決了“讀幻影行”的問題,同一個事務裡,前後連續的select讀到始終相同的結果集
2.5 不同隔離級別下快照讀的區別
2.5.1 案例解析1
事務執行順序如下:
時間序列 | A事務 | B事務 |
---|---|---|
T1 | 開始事務 | |
T2 | 開始事務 | |
T3 | 查詢xx賬戶餘額(假設預設有500元)★SELECT balance FROM acount WHERE customer_id=123456; |
|
T4 | xx賬戶存入1000元(未提交)★UPDATE acount SET balance=balance+1000.00 WHERE customer_id=123456; |
|
T5 | 查詢A賬戶餘額 | |
T6 | 提交事務★commit; |
|
T7 | 查詢A賬戶餘額 |
-
Repeated Read 隔離級別
- T3讀到的結果肯定是500,這是B事務的第一個read
- T5讀到的結果也是500,因為A事務還沒有提交
- T7讀到的結果還是500,因為A事務是在時間T5之後提交的,T7讀到和T5一樣的結果(重複讀)
-
Read Committed 隔離級別
- T3讀到的結果肯定是500,這是B事務的第一個read
- T5讀到的結果也是500,因為A事務還沒有提交
- T7讀到的結果還是1500,因為A事務已經提交,T7讀到Commit後的結果(讀已提交)
2.5.2 案例解析2
事務執行順序如下:
時間序列 | A事務 | B事務 |
---|---|---|
T1 | 開始事務(假設預設有500元) | |
T2 | 開始事務 | |
T3 | xx賬戶存入1000元(未提交)★UPDATE acount SET balance=balance+1000.00 WHERE customer_id=123456; |
|
T4 | 提交事務★commit; |
|
T5 | 查詢A賬戶餘額★SELECT balance FROM acount WHERE customer_id=123456; |
- Repeated Read 隔離級別:唯一的一次讀是在A事務提交之後的讀,所以結果肯定是1500
- Read Committed 隔離級別:讀取已提交之後的資料,所以毫無疑問依然是1500
2.6 區別總結
首先,事務總能夠讀取到自己寫入(update /insert /delete)的行記錄。而其他事務的提交,則分情況。
RC模式,快照讀總是能讀到最新的行資料快照,當然,必須是已提交事務寫入的。
RR模式,某個事務首次read記錄的時間為T1,之後的操作不會讀取到T1時間之後已提交事務寫入的記錄,以保證連續相同的read讀到相同的結果集。
簡單點說:
- RR下,事務在第一個Read操作時,會建立Read View,並貫穿整個事務的過程,保證了可重複讀的效果。
- RC下,事務在每次Read操作時,都會建立Read View,以保證獲取到的都是資料庫中最新的被Commit的值。