關於Mysql中快照讀幻讀問題一點思考

1、前言

因爲本身對於Mysql的事務隔離級別解決了什麼問題,它的原理是什麼,使用了什麼機制等都理解得比較模糊。就我目前的認知水平我姑且先總結幾點個人理解,以便於後面被顛覆,刷新本身的認知,從中取得進步。sql

  1. 讀未提交:未加任何鎖也沒有使用MVCC機制。當前事務內能夠讀取別的事務未提交的變動,從而引起髒讀、不可重複讀、幻讀等問題。
  2. 讀已提交:讀(select)操做不加鎖,同時使用MVCC機制,寫操做加行鎖。只會讀到小於等於當前事務版本號的記錄,解決了髒讀的問題,可是可重複讀、幻讀依然存在。
  3. 可重複讀:讀(select)操做不加鎖,同時使用MVCC機制,寫操做加行鎖、間隙鎖。因爲MVCC機制和間隙鎖的存在,解決了快照讀的可重複讀問題而且部分解決了快照讀的幻讀問題。依然存在個別狀況下快照讀幻讀問題及當前讀的幻讀問題。

2、實驗

針對於Mysql的默認隔離級別(可重複讀)下,爲何說部分解決了快照讀的幻讀問題呢?請看如下示例。併發

場景一

一、事務Aapp

BEGIN;
SELECT * FROM product_brand_info WHERE brand_id >= 0;
SELECT * FROM product_brand_info WHERE brand_id >= 0;
COMMIT;

二、事務Bspa

BEGIN;
SELECT * FROM product_brand_info WHERE brand_id >= 0;
INSERT INTO `product_db`.`product_brand_info`(`brand_name`, `telephone`, `brand_status`, `brand_order`, `modified_time`) VALUES ('kappa', '', 1, 0, NOW());
COMMIT;

三、說明
brand_id爲品牌表的自增id,以上兩個事務A、B併發執行,不管事務B是否提交事務,事務A中的查詢語句結果集裏面都不會出現事務B新增的記錄。這麼看來Mysql的默認事務隔離級別(可重複讀)已經解決了幻讀的問題,事實果然如此嗎?請接着看下一個場景。3d

場景二

一、事務Acode

BEGIN;
#1
SELECT * FROM product_brand_info WHERE brand_id >= 36;
#4
UPDATE `product_db`.`product_brand_info` SET `brand_name` = '鴻星爾克增強版' WHERE `brand_id` >=36;
#5
SELECT * FROM product_brand_info WHERE brand_id >= 36;
#6
COMMIT;

二、事務Bblog

BEGIN;
#2
INSERT INTO `product_db`.`product_brand_info`(`brand_name`, `telephone`, `brand_status`, `brand_order`, `modified_time`) VALUES ('kappa', '', 1, 0, NOW());
#3
COMMIT;

三、標號執行結果事務

  • 事務A操做一執行結果

image.png

  • 事務B操做二新增一條品牌記錄
  • 事務B操做三提交事務
  • 事務A操做四執行條件更新操做

image.png

  • 事務A操做五查詢操做

image.png

  • 事務A操做六提交

四、說明
主要注意事務A的操做四及操做五,操做四的更新操做影響了兩條記錄,此更新操做當前讀讀到了事務B的最新提交的數據並對其進行了更新,事務A的操做五查詢返回的結果集也返回了事務B插入的記錄。it

3、結論

根據以上實驗過程,加入自我思考及猜測。在Mysql默認的事務級別下,確實部分解決了快照讀的幻讀問題,這正是場景一所說明的問題,這得益於MVCC機制;可是它也僅僅是部分解決,場景二舉了反例說明,當前讀能讀到最新的事務提交結果,而且更新掉記錄的建立版本號爲當前事務版本號,因此當前事務內的查詢有可能會查詢到別的已提交事務新增的記錄,出現幻讀現象。class

相關文章
相關標籤/搜索