SQL的事務( 三 )

,則發生了臟讀)
⑤COMMIT;

ROLLBACK;已知表中僅有一條no為1、name為小明的記錄 。
Session A 與 Session B 各自開啟自己的事務,Session B 的事務先將no為1的記錄修改name列的值為李四 , 然后緊接著 Session A 查詢這條記錄,如果發現讀到的數據為李四,即讀到了Session B 中還沒有提交的數據,之后 Session B 進行了回滾,數據還原回小明 , 那么 Session A 讀到的李四就是一個不存在的數據,這種現象稱為臟讀 。
在某些場合下,返回不存在的數據、假的數據給客戶,是可能會出大問題的 。
3. 不可重復度(Non-Repeatable Read)對于兩個事務 Session A、Session B,Session A 讀取了一條記錄的一個字段 , 然后 Session B 修改了這條記錄的同個字段,接著 Session A 再重復上一次查詢 , 兩次結果不同了,這就發生了不可重復讀 。
不可重復讀示意圖
發生時間編號Session ASession B①BEGIN;
②SELECR * FROM student  WHERE no = 1; (此時讀出來是小明

BEGIN;UPDATE student SET name = '李四'  WHERE no = 1;COMMIT;④SELECR * FROM student  WHERE no = 1; (讀出來是李四,跟上次不同,則發生了不可重復讀)

BEGIN;UPDATE student SET name = '王五'  WHERE no = 1;COMMIT;⑥SELECR * FROM student  WHERE no = 1; (讀出來是王五,又跟上次不同,則發生了不可重復讀)
已知表中僅有一條no為1、name為小明的記錄 。
Session A 第一次查詢該記錄為小明(注意還沒有COMMIT) , 接著 Session B 修改該記錄為李四,然后 Session A 再次查詢發現變成李四了,跟上一次查詢結果不同,這種現象稱為不可重復讀 。同理 Session B 又修改值為王五 , 緊接著Session A 又再次查詢發現結果又變了,變成了王五,因為發生了不可重復讀 。
對于這種現象 , 在現實中很多場景下中我們會認為這是合理的、可以接受的 , 每次查詢就應該查出當前最新的數據,但處于并發事務內的角度來看這屬于一種問題 。
4. 幻讀(Phantom Read)對于兩個事務 Session A、Session B,Session A 讀取了一條記錄的一個字段,然后 Session B 往表插入一些新的記錄 , 之后 Session A 再次讀取發現多出了新的記錄,這就算幻讀 。
幻讀示意圖
發生時間編號Session ASession B①BEGIN;
②SELECR * FROM student  WHERE no > 0; (此時讀出來只有小明一條記錄)

BEGIN;INSERT INTO student VALUES(2, '李四', 19);COMMIT;④SELECR * FROM student  WHERE no > 0; (此時讀出來有小明、李四兩條記錄,發生了幻讀)
已知表中僅有一條no為1、name為小明的記錄 。
Session A 第一次查詢限定條件為 no > 0,查出來一條記錄為小明(注意還沒有COMMIT),接著 Session B 插入了一條記錄李四,然后 Session A 再次查詢結果為小明李四兩條記錄了 , 多了一條,這種現象稱為幻讀,而多出來的記錄稱為幻影記錄 。
對于這種現象,還是那句話,在現實中很多場景下中我們會認為這是合理的、可以接受的,但處于并發事務內的角度來看這屬于一種問題 。
對于幻讀的注意點:
幻讀強調的是多出來的記錄 。按照示意圖,如果 Session B 不是插入記錄,而是刪除記錄,那 Session A 再次查詢發現記錄數量變少了 , 這種現象不屬于幻讀 。由于第二次查變少了,嚴格歸類的話,這種現象屬于不可重復讀 。
5.3 SQL標準的四種隔離級別按照并發問題嚴重程度高到低排序:臟寫 > 臟讀 > 不可重復讀 > 幻讀
由于臟寫問題是無法接受的 , 所以現在市面主流數據庫都不會出現這個問題,那還剩下后面3個問題 。如果能把所有問題都解決那肯定最好 , 但也就意味著并發性能最差,如果要最高的并發性能,又會出現數據并發的問題......因此回到前面說的權衡取舍問題了,看不同的場景是要數據絕對準確性,還是要最高的并發性能 , 亦或犧牲部分并發性能以換取數據的相對準確

推薦閱讀