資料庫系列:RR和RC下,快照讀的區別

2023-11-22 15:00:48

資料庫系列: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的值。