標準SQL規範中定義的四個事務隔離級別(摘錄)

來源於網上

在標準SQL規範中,定義了4個事務隔離級別,不同的隔離級別對事務的處理不同:

◆未授權讀取(Read Uncommitted):允許髒讀取,但不允許更新丟失。如果一個事務已經開始寫數據,則另外一個數據則不允許同時進行寫操作,但允許其他事務讀此行數據。該隔離級別可以通過“排他寫鎖”實現。

◆授權讀取(Read Committed):允許不可重複讀取,但不允許髒讀取。這可以通過“瞬間共享讀鎖”和“排他寫鎖”實現。讀取數據的事務允許其他事務繼續訪問該行數據,但是未提交的寫事務將會禁止其他事務訪問該行。

◆可重複讀取(Repeatable Read):禁止不可重複讀取和髒讀取,但是有時可能出現幻影數據。這可以通過“共享讀鎖”和“排他寫鎖”實現。讀取數據的事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。

◆序列化(Serializable):提供嚴格的事務隔離。它要求事務序列化執行,事務只能一個接着一個地執行,但不能併發執行。如果僅僅通過“行級鎖”是無法實現事務序列化的,必須通過其他機制保證新插入的數據不會被剛執行查詢操作的事務訪問到。

隔離級別越高,越能保證數據的完整性和一致性,但是對併發性能的影響也越大。對於多數應用程序,可以優先考慮把數據庫系統的隔離級別設爲Read Committed,它能夠避免髒讀取,而且具有較好的併發性能。儘管它會導致不可重複讀、虛讀和第二類丟失更新這些併發問題,在可能出現這類問題的個別場合,可以由應用程序採用悲觀鎖或樂觀鎖來控制。

通過前面的介紹已經知道,通過選用不同的隔離等級就可以在不同程度上避免前面所提及的在事務處理中所面臨的各種問題。所以,數據庫隔離級別的選取就顯得尤爲重要,在選取數據庫的隔離級別時,應該注意以下幾個處理的原則:

首先,必須排除“未授權讀取”,因爲在多個事務之間使用它將會是非常危險的。事務的回滾操作或失敗將會影響到其他併發事務。第一個事務的回滾將會完全將其他事務的操作清除,甚至使數據庫處在一個不一致的狀態。很可能一個已回滾爲結束的事務對數據的修改最後卻修改提交了,因爲“未授權讀取”允許其他事務讀取數據,最後整個錯誤狀態在其他事務之間傳播開來。

其次,絕大部分應用都無須使用“序列化”隔離(一般來說,讀取幻影數據並不是一個問題),此隔離級別也難以測量。目前使用序列化隔離的應用中,一般都使用悲觀鎖,這樣強行使所有事務都序列化執行。

剩下的也就是在“授權讀取”和“可重複讀取”之間選擇了。我們先考慮可重複讀取。如果所有的數據訪問都是在統一的原子數據庫事務中,此隔離級別將消除一個事務在另外一個併發事務過程中覆蓋數據的可能性(第二個事務更新丟失問題)。這是一個非常重要的問題,但是使用可重複讀取並不是解決問題的唯一途徑。

假設使用了“版本數據”,Hibernate會自動使用版本數據。Hibernate的一級Session緩存和版本數據已經爲你提供了“可重複讀取隔離”絕大部分的特性。特別是,版本數據可以防止二次更新丟失的問題,一級Session緩存可以保證持久載入數據的狀態與其他事務對數據的修改隔離開來,因此如果使用對所有的數據庫事務採用授權讀取隔離和版本數據是行得通的。

“可重複讀取”爲數據庫查詢提供了更好的效率(僅對那些長時間的數據庫事務),但是由於幻影讀取依然存在,因此沒必要使用它(對於Web應用來說,一般也很少在一個數據庫事務中對同一個表查詢兩次)。

也可以同時考慮選擇使用Hibernate的二級緩存,它可以如同底層的數據庫事務一樣提供相同的事務隔離,但是它可能弱化隔離。假如在二級緩存大量使用緩存併發策略,它並不提供重複讀取語義(例如,後面章節中將要討論的讀寫,特別是非嚴格讀寫),很容易可以選擇默認的隔離級別:因爲無論如何都無法實現“可重複讀取”,因此就更沒有必要拖慢數據庫了。另一方面,可能對關鍵類不採用二級緩存,或者採用一個完全的事務緩存,提供“可重複讀取隔離”。那麼在業務中需要使用到“可重複讀取”嗎?如果你喜歡,當然可以那樣做,但更多的時候並沒有必要花費這個代價。

 

 

補充:

事務的四個屬性:原子性(atomicity)、一致性(consistency)、隔離性(isolation)和持久性(durability)。

1.原子性(Atomic)
    最重要的原則,也是最容易理解的原則。被事務管理的所有方法,要麼一起被提交,要麼一起回滾。

2.一致性(Consistency)
    事務在系統完整性中實施一致性,如果事務成功地完成,那麼系統中所有變化將正確地應用,系統處於新有效狀態。如果在事務中出現錯誤,那麼系統中的所有變化將自動地回滾,系統返回到原始狀態。

3.隔離性(Isolation)
    在隔離狀態執行事務,使它們好像是系統在給定時間內執行的唯一操作。如果有兩個事務,運行在相同的時間內,執行相同的功能,事務的隔離性將確保每一事務在系統中認爲只有該事務在使用系統。這種屬性有時稱爲串行化,爲了防止事務操作間的混淆,必須串行化或序列化請求,使得在同一時間僅有一個請求用於同一數據。重要的是,在隔離狀態執行事務,系統的狀態有可能是不一致的,在結束事務前,應確保系統處於一致狀態。但是在每個單獨的事務中,系統的狀態可能會發生變化。如果事務不是在隔離狀態運行,它就可能從系統中訪問數據,而系統可能處於不一致狀態。通過提供事務隔離,可以阻止這類事件的發生。

4.持久性(Durability)
    持久性意味着一旦事務執行成功,在系統中產生的所有變化將是永久的。應該存在一些檢查點防止在系統失敗時丟失信息。甚至硬件本身失敗,系統的狀態仍能通過在日誌中記錄事務完成的任務進行重建。

數據庫鎖概念:
    
在數據庫中有兩種基本的鎖類型:排它鎖(Exclusive Locks,即X鎖)和共享鎖(Share Locks,即S鎖)。當數據對象被加上排它鎖時,其他的事務不能對它讀取和修改。加了共享鎖的數據對象可以被其他事務讀取,但不能修改。數據庫利用這兩種基本的鎖類型來對數據庫的事務進行併發控制。
    從程序員的角度看,鎖分爲以下兩種類型: 
    1.樂觀鎖(Optimistic Lock) 
    樂觀鎖假定在處理數據時,不需要在應用程序的代碼中做任何事情就可以直接在記錄上加鎖、即完全依靠數據庫來管理鎖的工作。一般情況下,當執行事務處理時SQL Server會自動對事務處理範圍內更新到的表做鎖定。 
    2.悲觀鎖(Pessimistic Lock) 
    悲觀鎖對數據庫系統的自動管理不感冒,需要程序員直接管理數據或對象上的加鎖處理,並負責獲取、共享和放棄正在使用的數據上的任何鎖。

事務隔離級別
    
一個事務必須與其它事務進行隔離的程度。較低的隔離級別可以增加併發,但代價是降低數據的正確性。相反,較高的隔離級別可以確保數據的正確性,但可能對併發產生負面影響。

數據庫併發操作存在的異常情況:
1. 更新丟失(Lost update):兩個事務都同時更新一行數據但是第二個事務卻中途失敗退出導致對數據兩個修改都失效了這是系統沒有執行任何鎖操作因此併發事務並沒有被隔離開來

2. 髒讀取(Dirty Reads):一個事務開始讀取了某行數據但是另外一個事務已經更新了此數據但沒有能夠及時提交。這是相當危險很可能所有操作都被回滾

3. 不可重複讀取(Non-repeatable Reads):一個事務對同一行數據重複讀取兩次但是卻得到了不同結果。例如在兩次讀取中途有另外一個事務對該行數據進行了修改並提交

4. 兩次更新問題(Second lost updates problem):無法重複讀取特例,有兩個併發事務同時讀取同一行數據然後其中一個對它進行修改提交而另一個也進行了修改提交這就會造成第一次寫操作失效

5. 幻讀(Phantom Reads):也稱爲幻像(幻影)。事務在操作過程中進行兩次查詢,第二次查詢結果包含了第一次查詢中未出現的數據(這裏並不要求兩次查詢SQL語句相同)這是因爲在兩次查詢過程中有另外一個事務插入數據造成的

爲了避免上面出現幾種情況在標準SQL規範中定義了4個事務隔離級別,不同隔離級別對事務處理不同。

1.未授權讀取(Read Uncommitted):也稱未提交讀。允許髒讀取但不允許更新丟失,如果一個事務已經開始寫數據則另外一個數據則不允許同時進行寫操作但允許其他事務讀此行數據。該隔離級別可以通過“排他寫鎖”實現。事務隔離的最低級別,僅可保證不讀取物理損壞的數據。與READ COMMITTED 隔離級相反,它允許讀取已經被其它用戶修改但尚未提交確定的數據。

2. 授權讀取(Read Committed):也稱提交讀。允許不可重複讀取但不允許髒讀取。這可以通過“瞬間共享讀鎖”和“排他寫鎖”實現,讀取數據的事務允許其他事務繼續訪問該行數據,但是未提交寫事務將會禁止其他事務訪問該行。SQL Server 默認的級別。在此隔離級下,SELECT 命令不會返回尚未提交(Committed)的數據,也不能返回髒數據。

3. 可重複讀取(Repeatable Read):禁止不可重複讀取和髒讀取。但是有時可能出現幻影數據,這可以通過“共享讀鎖”和“排他寫鎖”實現,讀取數據事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。在此隔離級下,用SELECT 命令讀取的數據在整個命令執行過程中不會被更改。此選項會影響系統的效能,非必要情況最好不用此隔離級。

4. 串行(Serializable):也稱可串行讀。提供嚴格的事務隔離,它要求事務序列化執行,事務只能一個接着一個地執行,但不能併發執行。如果僅僅通過“行級鎖”是無法實現事務序列化的,必須通過其他機制保證新插入的數據不會被剛執行查詢操作事務訪問到。事務隔離的最高級別,事務之間完全隔離。如果事務在可串行讀隔離級別上運行,則可以保證任何併發重疊事務均是串行的。


隔離級別 更新丟失 髒讀取 重複讀取 幻讀
未授權讀取 N Y Y Y
授權讀取 N N Y Y
可重複讀取 N N N Y
串行 N N N N
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章