1. 程式人生 > >常見事務併發問題以及處理方法

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

1、資料庫事務併發會引起那些常見問題以及對應的解決方法?
1)丟失更新:撤消一個事務時,把其它事務已提交的更新的資料覆蓋了。
2)髒讀:一個事務讀到另一個事務未提交的更新資料。
3)幻讀:一個事務執行兩次查詢,但第二次查詢比第一次查詢多出了一些資料行。
4)不可重複讀:一個事務兩次讀同一行資料,可是這兩次讀到的資料不一樣。
---------------------------------------------------------------------------

2、事務隔離級別

為了解決多個事務併發會引發的問題。資料庫系統提供了四種事務隔離級別供使用者選擇。
? Serializable:序列化。隔離級別最高。
? Repeatable Read:可重複讀。
? Read Committed:讀已提交資料。
? Read Uncommitted:讀未提交資料。隔離級別最差。
資料庫系統採用不同的鎖型別來實現以上四種隔離級別,具體的實現過程對使用者是透明的。使用者應該關心的是如何選擇合適的隔離級別。
對於多數應用程式,可以優先考慮把資料庫系統的隔離級別設為Read Committed,它能夠避免髒讀,而且具有較好的併發效能。
每個資料庫連線都有一個全域性變數@@tx_isolation,表示當前的事務隔離級別。JDBC資料庫連線使用資料庫系統預設的隔離級別。在Hibernate的配置檔案中可以顯示地設定隔離級別。每一種隔離級別對應著一個正整數。
? Read Uncommitted: 1
? Read Committed: 2
? Repeatable Read: 4
? Serializable: 8
在hibernate.cfg.xml中設定隔離級別如下:
<session-factory>
 <!-- 設定JDBC的隔離級別 -->
 <property name="hibernate.connection.isolation">2</property>
</session-factory>
設定之後,在開始一個事務之前,Hibernate將為從連線池中獲得的JDBC連線設定級別。需要注意的是,在受管理環境中,如果Hibernate使用的資料庫連線來自於應用伺服器提供的資料來源,Hibernate不會改變這些連線的事務隔離級別。在這種情況下,應該通過修改應用伺服器的資料來源配置來修改隔離級別。
3、併發控制
當資料庫系統採用Red Committed隔離級別時,會導致不可重複讀和第二類丟失更新的併發問題,在可能出現這種問題的場合。可以在應用程式中採用悲觀鎖或樂觀鎖來避免這類問題。
4、 樂觀鎖(Optimistic Locking)
樂觀鎖假定當前事務操縱資料資源時,不會有其他事務同時訪問該資料資源,因此不作資料庫層次上的鎖定。為了維護正確的資料,樂觀鎖使用應用程式上的版本控制(由程式邏輯來實現的)來避免可能出現的併發問題。
唯一能夠同時保持高併發和高可伸縮性的方法就是使用帶版本化的樂觀併發控制。版本檢查使用版本號、 或者時間戳來檢測更新衝突(並且防止更新丟失)。
5、使用版本檢查(<version>)
Hibernate中通過版本號檢查來實現後更新為主,這也是Hibernate推薦的方式。在資料庫表中加入一個version(版本)欄位,在讀取資料時連同版本號一起讀取,並在更新資料時比較版本號與資料庫表中的版本號,如果等於資料庫表中的版本號則予以更新,並遞增版本號,如果小於資料庫表中的版本號就丟擲異常。
6、使用時間戳(<timestamp>)
跟版本檢查的用法相似。不再多說。
7、悲觀鎖(Pessimistic Locking)

悲觀鎖假定當前事務操縱資料資源時,肯定還會有其他事務同時訪問該資料資源,為了避免當前事務的操作受到干擾,先鎖定資源。儘管悲觀鎖能夠防止丟失更新和不可重複讀這類併發問題,但是它影響併發效能,因此應該很謹慎地使用悲觀鎖。

8、當一個事務訪問某個資料庫資源時,如果執行的是select語句,必須為資源加上共享鎖,如果執行的是insert,update,delete語句,必須為資源加上排他鎖,這些鎖鎖定正在被操作的資源。

9、當第二個事務也要反問相同的資源時,如果執行的select語句,那麼也必須為資源加上共享鎖;如果執行的是insert,update,或delete語句,也必須為資源加上排他鎖。但此時第二個事務並非就立即能為資源加上鎖,當第一個事務為資源加的是共享鎖時,第二個事務能夠為資源加上共享鎖,但當第一個事務為資源加的是排他鎖時,第二個事務必須等待第一個事務結束,才能為資源加上排他鎖。

        上面已經引出了,共享鎖,排他鎖。下面來闡述一下鎖的種類及概念。

        1.共享鎖

        共享鎖用於讀取資料操作,它允許其他事務同時讀取鎖定的資源,但不允許其他事務更新它。

        2.排他鎖

       排他鎖用於修改資料的場合,他鎖定的資源,其他事務部能讀取也不能修改。

       3.更新鎖

        更新鎖在更新操作初始化截斷用來鎖定可能要被修改的資源,從而避免使用共享鎖造成的死鎖現象。