數據庫系列: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的值。