1. 程式人生 > 程式設計 >淺談spring中isolation和propagation的用法

淺談spring中isolation和propagation的用法

可以在XML檔案中進行配置,下面的程式碼是個示意程式碼

<tx:advice id="txAdvice" transaction-manager="txManager">
 <tx:attributes>
 <tx:method name="add*" propagation="REQUIRED" isolation="READ_COMMITTED"/>增加記錄的方法
 <tx:method name="get*" propagation="REQUIRED" isolation="READ_COMMITTED"/>獲取記錄的方法
 <tx:method name="delete*" propagation="REQUIRED" isolation="READ_COMMITTED"/>刪除的方法
 <tx:method name="update*" propagation="REQUIRED" isolation="SERIALIZABLE"/>更改記錄的方法
 </tx:attributes>
 </tx:advice>

下面擴充套件將一下spring裡面事務的傳播屬性和事務隔離級別。

一、Propagation (事務的傳播屬性)

Propagationkey屬性確定代理應該給哪個方法增加事務行為。這樣的屬性最重要的部份是傳播行為。有以下選項可供使用:

傳播行為

事務的第一個方面是傳播行為。傳播行為定義關於客戶端和被呼叫方法的事務邊界。Spring定義了7中傳播行為。

傳播行為 意義
PROPAGATION_REQUIRES 表示當前方法必須在一個事務中執行。如果一個現有事務正在進行中,該方法將在那個事務中執行,否則就要開始一個新事務。
PROPAGATION_SUPPORTS 表示當前方法不需要事務性上下文,但是如果有一個事務已經在執行的話,它也可以在這個事務裡執行。
PROPAGATION_MANDATORY 表示該方法必須執行在一個事務中。如果當前沒有事務正在發生,將丟擲一個異常。
PROPAGATION_REQUIRES_NEW 表示當前方法必須在它自己的事務裡執行。一個新的事務將被啟動,而且如果有一個現有事務在執行的話,則將在這個方法執行期間被掛起。
PROPAGATION_NOT_SUPPORTED 表示當前方法不需要事務性上下文,但是如果有一個事務已經在執行的話,它也可以在這個事務裡執行。
PROPAGATION_NEVER 表示當前的方法不應該在一個事務中執行。如果一個事務正在進行,則會丟擲一個異常。
PROPAGATION_NESTED 表示如果當前正有一個事務在進行中,則該方法應當執行在一個巢狀式事務中。被巢狀的事務可以獨立於封裝事務進行提交或回滾。如果封裝事務不存在,行為就像PROPAGATION_REQUIRES一樣。

傳播規則回答了這樣一個問題,就是一個新的事務應該被啟動還是被掛起,或者是一個方法是否應該在事務性上下文中執行。

隔離級別

宣告式事務的第二個方面是隔離級別。隔離級別定義一個事務可能受其他併發事務活動活動影響的程度。另一種考慮一個事務的隔離級別的方式,是把它想象為那個事務對於事物處理資料的自私程度。

在一個典型的應用程式中,多個事務同時執行,經常會為了完成他們的工作而操作同一個資料。併發雖然是必需的,但是會導致一下問題:

  • 髒讀(Dirty read)-- 髒讀發生在一個事務讀取了被另一個事務改寫但尚未提交的資料時。如果這些改變在稍後被回滾了,那麼第一個事務讀取的資料就會是無效的。
  • 不可重複讀(Nonrepeatable read)-- 不可重複讀發生在一個事務執行相同的查詢兩次或兩次以上,但每次查詢結果都不相同時。這通常是由於另一個併發事務在兩次查詢之間更新了資料。
  • 幻影讀(Phantom reads)-- 幻影讀和不可重複讀相似。當一個事務(T1)讀取幾行記錄後,另一個併發事務(T2)插入了一些記錄時,幻影讀就發生了。在後來的查詢中,第一個事務(T1)就會發現一些原來沒有的額外記錄。

在理想狀態下,事務之間將完全隔離,從而可以防止這些問題發生。然而,完全隔離會影響效能,因為隔離經常牽扯到鎖定在資料庫中的記錄(而且有時是鎖定完整的資料表)。侵佔性的鎖定會阻礙併發,要求事務相互等待來完成工作。

考慮到完全隔離會影響效能,而且並不是所有應用程式都要求完全隔離,所以有時可以在事務隔離方面靈活處理。因此,就會有好幾個隔離級別。

隔離級別 含義
ISOLATION_DEFAULT 使用後端資料庫預設的隔離級別。
ISOLATION_READ_UNCOMMITTED 允許讀取尚未提交的更改。可能導致髒讀、幻影讀或不可重複讀。
ISOLATION_READ_COMMITTED 允許從已經提交的併發事務讀取。可防止髒讀,但幻影讀和不可重複讀仍可能會發生。
ISOLATION_REPEATABLE_READ 對相同欄位的多次讀取的結果是一致的,除非資料被當前事務本身改變。可防止髒讀和不可重複讀,但幻影讀仍可能發生。 
ISOLATION_SERIALIZABLE 完全服從ACID的隔離級別,確保不發生髒讀、不可重複讀和幻影讀。這在所有隔離級別中也是最慢的,因為它通常是通過完全鎖定當前事務所涉及的資料表來完成的。

只讀

宣告式事務的第三個特性是它是否是一個只讀事務。如果一個事務只對後端資料庫執行讀操作,那麼該資料庫就可能利用那個事務的只讀特性,採取某些優化 措施。通過把一個事務宣告為只讀,可以給後端資料庫一個機會來應用那些它認為合適的優化措施。由於只讀的優化措施是在一個事務啟動時由後端資料庫實施的, 因此,只有對於那些具有可能啟動一個新事務的傳播行為(PROPAGATION_REQUIRES_NEW、PROPAGATION_REQUIRED、 ROPAGATION_NESTED)的方法來說,將事務宣告為只讀才有意義。

此外,如果使用Hibernate作為持久化機制,那麼把一個事務宣告為只讀,將使Hibernate的flush模式被設定為FLUSH_NEVER。這就告訴Hibernate避免和資料庫進行不必要的物件同步,從而把所有更新延遲到事務的結束。

事務超時

為了使一個應用程式很好地執行,它的事務不能執行太長時間。因此,宣告式事務的下一個特性就是它的超時。

假設事務的執行時間變得格外的長,由於事務可能涉及對後端資料庫的鎖定,所以長時間執行的事務會不必要地佔用資料庫資源。這時就可以宣告一個事務在特定秒數後自動回滾,不必等它自己結束。

由於超時時鐘在一個事務啟動的時候開始的,因此,只有對於那些具有可能啟動一個新事務的傳播行為(PROPAGATION_REQUIRES_NEW、PROPAGATION_REQUIRED、ROPAGATION_NESTED)的方法來說,宣告事務超時才有意義。

回滾規則

事務五邊形的對後一個邊是一組規則,它們定義哪些異常引起回滾,哪些不引起。在預設設定下,事務只在出現執行時異常(runtime exception)時回滾,而在出現受檢查異常(checked exception)時不回滾(這一行為和EJB中的回滾行為是一致的)。

不過,也可以宣告在出現特定受檢查異常時像執行時異常一樣回滾。同樣,也可以宣告一個事務在出現特定的異常時不回滾,即使那些異常是執行時一場。

到此這篇關於淺談spring中isolation 和propagation的用法的文章就介紹到這了,更多相關spring isolation propagation內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!