1. 程式人生 > >理解資料庫事務隔離級別以及髒讀, 不可重複讀, 幻讀

理解資料庫事務隔離級別以及髒讀, 不可重複讀, 幻讀

資料庫事務的4個特性:
原子性(atomic):
 都成功或者都失敗;
一致性(consistency):事務操作之後,資料庫所處的狀態和業務規則是一致的;比如a,b賬戶相互轉賬之後,總金額不變;
隔離性(isolation):操作中的事務不相互影響;
永續性(durability):事務提交後被持久化到資料庫.

髒讀,不可重複讀, 幻讀
幻讀phantom read:
事務1讀取記錄時事務2增加了記錄並提交,事務1再次讀取時可以看到事務2新增的記錄;
不可重複讀unrepeatable read:事務1讀取記錄時,事務2更新了記錄並提交,事務1再次讀取時可以看到事務2修改後的記錄;
髒讀dirty read:

事務1更新了記錄,但沒有提交,事務2讀取了更新後的行,然後事務T1回滾,現在T2讀取無效。

事務隔離級別描述:
READ UNCOMMITTED:幻讀,不可重複讀和髒讀均允許;
READ COMMITTED:允許幻讀和不可重複讀,但不允許髒讀;
REPEATABLE READ:允許幻讀,但不允許不可重複讀和髒讀;
SERIALIZABLE:幻讀,不可重複讀和髒讀都不允許; 
ORACLE預設的是 READ COMMITTED。

如何感性理解這些“深奧”的術語?個人認為, 作為一個java程式設計師,這些字眼比較唬人。

首先, 隔離級別描述了事務被隔離的程度。可以簡單的想象一下, 一個人因為某種原因(比如國家安全)需要被隔離,則涉及安全的機密程度越高, 需要個隔離級別就越高,他與外界的溝通渠道就越少。

對於資料庫而言, 每個事務都要佔用一些資源,比如對錶/資料享有的操作許可權,事務的隔離級別描述了事務對資源享用的程度。

如果資料庫的隔離級別為REAE_UNCOMMITTED, 則其他執行緒可以看到未提交的資料, 因此就出現髒讀;

如果資料庫隔離級別設為READ_COMMITTED,即沒提交的資料別人是看不見的,就避免了髒讀;但是,正在讀取的資料只獲得了讀取鎖,讀完之後就解鎖,不管當前事務有沒有結束,這樣就容許其他事務修改本事務正在讀取的資料。導致不可重複讀。

REPEATABLE READ因為對正在操作的資料加鎖,並且只有等到事務結束才放開鎖, 則可以避免不可重複讀;
REPEATABLE READ

只能保證正在被本事務操作的資料不被其他事務修改,卻無法保證有其他事務提交新的資料。 則有可能執行緒1在操作表T1的時候(特別是統計性的事務),其他執行緒仍然可以提交新資料到表T1,這樣會導致執行緒1兩次統計的結果不一致,就像發生幻覺一樣。

SERIALIZABLE因為獲得範圍鎖,且事務是一個接著一個序列執行,則保證了不會發生幻讀。
由此可見,隔離級別越高,受其他事物干擾越少,併發效能越差。

設定語法

Oracle:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE|READ COMMITTED|READ UNCOMMITTED|REPEATABLE READ;

Sybase:

sql opreation at isolation read committed