RC隔離級別
RC
的本質就是事務中每一條SELECT
語句均可以看到其他已提交事務對數據的修改,那麼只要該事物已經提交其結果就是可見的,與這兩個事務開始的先後順序無關,不完全適用於 MVCC 讀。
RR隔離級別
RR
的本質是從第一個SELECT
語句生成ReadView
開始,任何已經提交過的事務的修改均可見
幻讀
- 事務T1讀取了滿足某條件的一個數據集,事務T2插入了一行或者多行數據滿足了T1的選擇條件,導致事務T1再次使用同樣的選擇條件讀取的時候,得到了比第一次讀取更多的數據集。
實驗
-
準備數據
DROP TABLE IF EXISTS `t_test`; CREATE TABLE `t_test` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `a` varchar(10) CHARACTER SET utf8 NOT NULL, `b` varchar(10) CHARACTER SET utf8 NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; BEGIN; INSERT INTO `t_test` VALUES (1, 'a1', 'b1'); INSERT INTO `t_test` VALUES (2, 'a1', 'b2'); INSERT INTO `t_test` VALUES (3, 'a2', 'b3'); INSERT INTO `t_test` VALUES (4, 'a3', 'b4'); COMMIT;
-
幻讀演示一,不會產生幻讀
-
幻讀演示二,會產生幻讀
-
幻讀演示三,會產生幻讀
-
在RR級別中,數據是可重複讀,對於這種讀取歷史數據的方式,叫做快照讀(snapshot read),讀取數據庫當前版本數據的方式,叫當前讀 (current read)。
- 快照讀就是普通的select
- select * from table
- 當前讀:特殊的讀操作,插入/更新/刪除操作,屬於當前讀,處理的都是當前的數據,需要加鎖
- select * from table where xxx lock in share mode;
- select * from table where xxx for update
- Insert into
- update
- delete
- 快照讀就是普通的select
-
在快照讀情況下,mysql通過mvcc(多版本併發控制)來避免幻讀。在當前讀讀情況下,mysql通過next-key來避免幻讀。
select * from t where a=1;屬於快照讀 select * from t where a=1 lock in share mode;屬於當前讀 在RR級別下,如果是快照讀,那麼其實是可以避免幻讀的。如果是快照讀+當前讀,那麼其實是不能避免幻讀的