髒讀 幻讀 不可重複讀 及其解決方法
一個事務讀到另外一個事務還沒有提交的資料,我們稱之為髒讀。解決方法:把事務隔離級別調整到READ
COMMITTED
一個事務先後讀取同一條記錄,但兩次讀取的資料不同,我們稱之為不可重複讀。解決方法:把事務隔離級別調整到REPEATABLE READ。
一個事務先後讀取一個範圍的記錄,但兩次讀取的紀錄數不同,我們稱之為幻象讀。解決方法:把事務隔離級別調整到SERIALIZABLE。
1, 髒讀
一個事務讀到另一個事務,尚未提交的修改,就是髒讀。這裡所謂的修改,除了Update操作,不要忘了,還包括
Insert和Delete操作。
髒讀的後果:如果後一個事務回滾,那麼它所做的修改,統統都會被撤銷。前一個事務讀到的資料,就是垃圾資料。
舉個例子:預訂房間。
有一張Reservation表,往表中插入一條記錄,來訂購一個房間。
事務1:在Reservation表中插入一條記錄,用於預訂99號房間。
事務2:查詢,尚未預定的房間列表,因為99號房間,已經被事務1預訂。所以不在列表中。
事務1:信用卡付款。由於付款失敗,導致整個事務回滾。
所以插入到Reservation 表中的記錄並不置為持久(即它將被刪除)。
現在99號房間則為可用。
所以,事務2所用的是一個無效的房間列表,因為99號房間,已經可用。如果它是最後一個沒有被預定的房間,那麼這將是一個嚴重的失誤。
注:髒讀的後果很嚴重。
2,不可重複讀。
在同一個事務中,再次讀取資料時【就是你的select操作】,所讀取的資料,和第1次讀取的資料,不一樣了。就是不可重複讀。
舉個例子:
事務1:查詢99號房間是否為雙人床房間。結果99號是。
事務2:將99號房間,改成單人床房間。
事務1:再次執行查詢,99號房間不是雙人房了。也就是說, 事務1,可以看到其他事務所做的修改。
在不可重複讀,裡面,可以看到其他事務所做的修改,而導致2次的查詢結果不再一樣了。
這裡的修改,是提交過的。也可以是沒有提交的,這種情況同時也是髒讀。
如果,資料庫系統的隔離級別。允許,不可重複讀。那麼你啟動一個事務,並做一個select查詢操作。
查詢到的資料,就有可能,和你第2次,3次...n次,查詢到的資料不一樣。一般情況下,你只會做一次,select
查詢,並以這一次的查詢資料,作為後續計算的基礎。因為允許出現,不可重複讀。那麼任何
時候,查詢到的資料,都有可能被其他事務更新,查詢的結果將是不確定的。
注:如果允許,不可重複讀,你的查詢結果,將是不確定的。一個不確定的結果,你能容忍嗎?
3,幻讀
事務1讀取指定的where子句所返回的一些行。然後,事務2插入一個新行,這個新行也滿足事務1使用的查詢
where子句。然後事務1再次使用相同的查詢讀取行,但是現在它看到了事務2剛插入的行。這個行被稱為幻象,
因為對事務1來說,這一行的出現是不可思議的。
舉個例子:
事務1:請求沒有預定的,雙人床房間列表。99號在其中。
事務2:向Reservation表中插入一個新紀錄,以預訂99號房間,並提交。
事務1:再次請求有雙人床的未預定的房間列表,99號房間,不再位於列表中。
注:幻讀,針對的是,Insert操作。如果事務2,插入的記錄,沒有提交。那麼同時也是髒讀。