事務併發問題以及處理方法

事務併發問題:

1. 第一類丟失更新(lost update): 在完全未隔離事務的情況下,兩個事物更新同一條數據資源,某一事物異常終止,回滾造成第一個完成的更新也同時丟失。
2. 髒讀(dirty read):如果第二個事務查詢到第一個事務還未提交的更新數據,形成髒讀。
3. 虛讀(phantom read):一個事務執行兩次查詢,第二次查詢比第一次多出或少一些數據,造成兩次結果不一致。只是另一個事務在這兩次查詢中間插入或者刪除了數據造成的。
4. 不可重複讀(unrepeated read):一個事務兩次讀取同一行數據,結果得到不同狀態結果,如中間正好另一個事務更新了該數據,兩次結果相異,不可信任。
5. 第二類丟失更新(second lost updates):是不可重複讀的特殊情況,如果兩個事務都讀取同一行,然後兩個都進行寫操作,並提交,第一個事務所做的改變就會丟失。

事務隔離級別:

爲了解決數據庫事務併發運行時的各種問題數據庫系統提供四種事務隔離級別:
1. Serializable 串行化
2. Repeatable Read 可重複讀
3. Read Commited 可讀已提交
4. Read Uncommited 可讀未提交

併發控制:

1.數據庫系統採用不同的鎖類型來實現以上四種隔離級別,具體的實現過程對用戶是透明的。用戶應該關心的是如何選擇合適的隔離級別。
2.對於多數應用程序,可以優先考慮把數據庫系統的隔離級別設爲Read Committed,它能夠避免髒讀,而且具有較好的併發性能。
3.每個數據庫連接都有一個全局變量@@tx_isolation,表示當前的事務隔離級別。JDBC數據庫連接使用數據庫系統默認的隔離級別。
4.在Hibernate的配置文件中可以顯示地設置隔離級別。每一種隔離級別對應着一個正整數。
5.需要注意的是,在受管理環境中,如果Hibernate使用的數據庫連接來自於應用服務器提供的數據源,Hibernate不會改變這些連接的事務隔離級別。在這種情況下,應該通過修改應用服務器的數據源配置來修改隔離級別。

6.當數據庫系統採用Red Committed隔離級別時,會導致不可重複讀和第二類丟失更新的併發問題,在可能出現這種問題的場合。可以在應用程序中採用悲觀鎖或樂觀鎖來避免這類問題。

悲觀鎖
  正如其名,它指的是對數據被外界(包括本系統當前的其他事務,以及來自外部系統的事務處理)修改持保守態度,因此,在整個數據處理過程中,將數據處於鎖定狀態。悲觀鎖的實現,往往依靠數據庫提供的鎖機制(也只有數據庫層提供的鎖機制才能真正保證數據訪問的排他性,否則,即使在本系統中實現了加鎖機制,也無法保證外部系統不會修改數據)。
  一個典型的依賴數據庫的悲觀鎖調用:select * from account where name=”Erica” for update這條 sql 語句鎖定了 account 表中所有符合檢索條件( name=”Erica” )的記錄。本次事務提交之前(事務提交時會釋放事務過程中的鎖),外界無法修改這些記錄。悲觀鎖,也是基於數據庫的鎖機制實現。
  在Hibernate使用悲觀鎖十分容易,但實際應用中悲觀鎖是很少被使用的,因爲它每次發送的SQL語句都會加上"for update"用於告訴數據庫鎖定相關數據,大大限制了併發性:
樂觀鎖
  相對悲觀鎖而言,樂觀鎖機制採取了更加寬鬆的加鎖機制。悲觀鎖大多數情況下依靠數據庫的鎖機制實現,以保證操作最大程度的獨佔性。但隨之而來的就是數據庫性能的大量開銷,特別是對長事務而言,這樣的開銷往往無法承受。樂觀鎖機制在一定程度上解決了這個問題。樂觀鎖,大多是基於數據版本(Version)記錄機制實現。何謂數據版本?即爲數據增加一個版本標識,在基於數據庫表的版本解決方案中,一般是通過爲數據庫表增加一個"version"字段來實現。
  樂觀鎖的工作原理:讀取出數據時,將此版本號一同讀出,之後更新時,對此版本號加一。此時,將提交數據的版本數據與數據庫表對應記錄的當前版本信息進行比對,如果提交的數據版本號大於數據庫表當前版本號,則予以更新,否則認爲是過期數據。
Hibernate爲樂觀鎖提供了3中實現:
1. 基於version
2. 基於timestamp
3. 爲遺留項目添加添加樂觀鎖 Hibernate爲樂觀鎖提供了3中實現

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