InnoDB,快照讀,在RR和RC下有何差異?(很多人,以為自己懂了...)
什么是快照讀(Snapshot Read)?
MySQL數據庫,InnoDB存儲引擎,為了提高并發,使用MVCC機制,在并發事務時,通過讀取數據行的歷史數據版本,不加鎖,來提高并發的一種不加鎖一致性讀(Consistent Nonlocking Read)。
畫外音:本文所有討論基于MySQL-InnoDB。
快照讀的內核原理,詳見:《??InnoDB并發如此高,原因竟然在這???》
什么是讀提交(Read Committed)?
(1)數據庫領域,事務隔離級別的一種,簡稱RC;
(2)它解決“讀臟”問題,保證讀取到的數據行都是已提交事務寫入的;
(3)它可能存在“讀幻影行”問題,同一個事務里,連續相同的read可能讀到不同的結果集;
什么是可重復讀(Repeated Read)?
(1)數據庫領域,事務隔離級別的一種,簡稱RR;
(2)它不但解決“讀臟”問題,還部分解決了“讀幻影行”問題,同一個事務里,連續相同的read讀到相同的結果集;
在讀提交(RC),可重復讀(RR)兩個不同的事務的隔離級別下,快照讀有什么不同呢?我們一起來做一些實驗。
假設有InnoDB表:
t(id PK, name);
表中有三條記錄:
- shenjian
- zhangsan
- lisi
case 1,兩個并發事務A,B執行的時間序列如下(A先于B開始,B先于A結束):
A1: start transaction;
B1: start transaction;
A2: select * from t;
B2: insert into t values (4, wangwu);
A3: select * from t;
B3: commit;
A4: select * from t;
提問1:假設事務的隔離級別是可重復讀RR,事務A中的三次查詢,A2, A3, A4分別讀到什么結果集?
提問2:假設事務的隔離級別是讀提交RC,A2, A3, A4又分別讀到什么結果集呢?
case 2,仍然是上面的兩個事務,只是A和B開始時間稍有不同(B先于A開始,B先于A結束):
B1: start transaction;
A1: start transaction;
A2: select * from t;
B2: insert into t values (4, wangwu);
A3: select * from t;
B3: commit;
A4: select * from t;
提問3:假設事務的隔離級別是可重復讀RR,事務A中的三次查詢,A2, A3, A4分別讀到什么結果集?
提問4:假設事務的隔離級別是讀提交RC,A2, A3, A4的結果集又是什么呢?
case 3,仍然是并發的事務A與B(A先于B開始,B先于A結束):
A1: start transaction;
B1: start transaction;
B2: insert into t values (4, wangwu);
B3: commit;
A2: select * from t;
提問5:假設事務的隔離級別是可重復讀RR,事務A中的A2查詢,結果集是什么?
提問6:假設事務的隔離級別是讀提交RC,A2的結果集又是什么呢?
case 4,事務開始的時間再換一下(B先于A開始,B先于A結束):
case 4,事務開始的時間再換一下(B先于A開始,B先于A結束):
B1: start transaction;
A1: start transaction;
B2: insert into t values (4, wangwu);
B3: commit;
A2: select * from t;
提問7:假設事務的隔離級別是可重復讀RR,事務A中的A2查詢,結果集是什么?
提問8:假設事務的隔離級別是讀提交RC,A2的結果集又是什么呢?
很多時候,我們以為自己懂了,其實...