事務隔離級別

事務隔離級別:一個事務對數據庫的修改與並行的另一個事務的隔離程度。

兩個併發事務同時訪問數據庫表相同的行時,這些問題可以歸結爲5類:

3類數據讀問題(髒讀、不可重複讀和幻象讀)
2類數據更新問題(第一類丟失更新和第二類丟失更新)。

1、幻想讀事務T1讀取一條指定where條件的語句,返回結果集。此時事務T2插入一行新記錄,恰好滿足T1的where條件。然後T1使用相同的條件再次查詢,結果集中可以看到T2插入的記錄,這條新紀錄就是幻想。

2、不可重複讀取事務T1讀取一行記錄,緊接着事務T2修改了T1剛剛讀取的記錄,然後T1再次查詢,發現與第一次讀取的記錄不同,這稱爲不可重複讀。

3、髒讀事務T1更新了一行記錄,還未提交所做的修改,這個T2讀取了更新後的數據,然後T1執行回滾操作,取消剛纔的修改,所以T2所讀取的行就無效,也就是髒數據。

4、第一類丟失更新 

A事務撤銷時,把已經提交的B事務的更新數據覆蓋了。這種錯誤可能造成很嚴重的問題,通過下面的賬戶取款轉賬就可以看出來: 



第二類丟失更新 

A事務覆蓋B事務已經提交的數據,造成B事務所做操作丟失



爲了處理這些問題,SQL標準定義了以下幾種事務隔離級別


Oracle數據庫支持READ COMMITTED 和 SERIALIZABLE這兩種事務隔離級別。所以Oracle不支持髒讀

SQL標準所定義的默認事務隔離級別是SERIALIZABLE,但是Oracle 默認使用的是READ COMMITTED

爲避免出現第二類更新丟失

sql_1:select 1 from dual for update;
sql_2:select 1 from dual for update;
sql_3:select 1 from dual for update nowait;

執行sql_1,不提交,表dual被鎖

分支1):執行sql_2,sql_2被阻塞,等待sql_1提交

分支2):執行sql_3,因爲有nowait,所以立即返回錯誤信息 "ORA-00054 : 資源正忙,但指定以NOWAIT方式獲取資源"

總結:nowait關鍵字,通知Oracle該sql語句採用非阻塞的方式修改或刪除數據,如果發現涉及到的數據被佔有(被鎖),則立即通知Oracle該資源被佔用,返回錯誤信息



在SQL92標準中,事務隔離級別分爲四種,分別爲:Read UncommittedRead CommittedRead RepeatableSerializable

其中Read Uncommitted與Read Committed爲語句級別的,而Read Repeatable與Serializable是針對事務級別的。

在Oracle和SQL Server中設置事務隔離級別的語句是相同的,都使用SQL92標準語法,即:

Set Transaction Isolation Level Read Committed

 

 1.SQL Server中的隔離級別及實現機制

 

  在SQL Server中提供了所有這四種隔離級別。

 

  Read Uncommitted

  一個會話可以讀取其他事務未提交的更新結果,如果這個事務最後以回滾結束,這時的讀取結果就可能是錯誤的,所以多數的數據庫應用都不會使用這種隔離級別。

  Read Committed

  這是SQL Server的缺省隔離級別,設置爲這種隔離級別的事務只能讀取其他事務已經提交的更新結果,否則,發生等待,但是其他會話可以修改這個事務中被讀取的記錄,而不必等待事務結束,顯然,在這種隔離級別下,一個事務中的兩個相同的讀取操作,其結果可能不同

  Read Repeatable

  在一個事務中,如果在兩次相同條件的讀取操作之間沒有添加記錄的操作,也沒有其他更新操作導致在這個查詢條件下記錄數增多,則兩次讀取結果相同。換句話說,就是在一個事務中第一次讀取的記錄保證不會在這個事務期間發生改變。SQL Server是通過在整個事務期間給讀取的記錄加鎖實現這種隔離級別的,這樣,在這個事務結束前,其他會話不能修改事務中讀取的記錄,而只能等待事務結束,但是SQL Server不會阻礙其他會話向表中添加記錄,也不阻礙其他會話修改其他記錄(其他會話:不能修改當前會話讀的數據,但是可以添加數據---》可以幻想讀)

  Serializable

  在一個事務中,讀取操作的結果是在這個事務開始之前其他事務就已經提交的記錄,SQL Server通過在整個事務期間給表加鎖實現這種隔離級別。在這種隔離級別下,對這個表的所有DML操作都是不允許的,即要等待事務結束,這樣就保證了在一個事務中的兩次讀取操作的結果肯定是相同的。

 

  2.Oracle中的隔離級別及實現機制

 

  在Oracle中,沒有Read Uncommitted及Repeatable Read隔離級別,這樣在Oracle中不允許一個會話讀取其他事務未提交的數據修改結果,從而避免了由於事務回滾發生的讀取錯誤。Oracle中的Read Committed和Serializable級別,其含義與SQL Server類似,但是實現方式卻大不一樣。

 

  在Oracle中,存在所謂的回滾段(Oracle9i之前版本)或撤銷段(Oracle9i版本),Oracle在修改數據記錄時,會把這些記錄被修改之前的結果存入回滾段或撤銷段中,就是因爲這種機制,Oracle對於事務隔離級別的實現與SQL Server截然不同。在Oracle中,讀取操作不會阻礙更新操作,更新操作也不會阻礙讀取操作,這樣在Oracle中的各種隔離級別下,讀取操作都不會等待更新事務結束,更新操作也不會因爲另一個事務中的讀取操作而發生等待,這也是Oracle事務處理的一個優勢所在。

  Read Committed

  Oracle缺省的設置是Read Committed隔離級別(也稱爲語句級別的隔離),在這種隔離級別下,如果一個事務正在對某個表進行DML操作,而這時另外一個會話對這個表的記錄進行讀取操作,則Oracle會去讀取回滾段或撤銷段中存放的更新之前的記錄,而不會象SQL Server一樣等待更新事務的結束。

 Serializable

  在Serializable隔離級別(也稱爲事務級別的隔離),事務中的讀取操作只能讀取這個事務開始之前已經提交的數據結果。如果在讀取時,其他事務正在對記錄進行修改,則Oracle就會在回滾段或撤銷段中去尋找對應的原來未經更改的記錄(而且是在讀取操作所在的事務開始之前存放於回滾段或撤銷段的記錄),這時讀取操作也不會因爲相應記錄被更新而等待。

來源:http://blog.csdn.net/gaogaoshan/article/details/21158949

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章