1. 程式人生 > >Spring的學習(十三)——Spring事務管理

Spring的學習(十三)——Spring事務管理

一、事務簡介

事務(Transaction),一般是指要做的或所做的事情。在計算機術語中是指訪問並可能更新資料庫中各種資料項的一個程式執行單元(unit)。

這裡我們以取錢的例子來講解:比如你去ATM機取1000塊錢,大體有兩個步驟:第一步輸入密碼金額,銀行卡扣掉1000元錢;第二步從ATM出1000元錢。這兩個步驟必須是要麼都執行要麼都不執行。如果銀行卡扣除了1000塊但是ATM出錢失敗的話,你將會損失1000元;如果銀行卡扣錢失敗但是ATM卻出了1000塊,那麼銀行將損失1000元。

如何保證這兩個步驟不會出現一個出現異常了,而另一個執行成功呢?事務就是用來解決這樣的問題。事務是一系列的動作,它們綜合在一起才是一個完整的工作單元,這些動作必須全部完成,如果有一個失敗的話,那麼事務就會回滾到最開始的狀態,彷彿什麼都沒發生過一樣。 在企業級應用程式開發中,事務管理是必不可少的技術,用來確保資料的完整性和一致性。

二、事務四大特性(ACID)

①、原子性(Atomicity):事務是一個原子操作,由一系列動作組成。事務的原子性確保動作要麼全部完成,要麼完全不起作用。

②、一致性(Consistency):一旦事務完成(不管成功還是失敗),系統必須確保它所建模的業務處於一致的狀態,而不會是部分完成部分失敗。在現實中的資料不應該被破壞。

③、隔離性(Isolation):可能有許多事務會同時處理相同的資料,因此每個事務都應該與其他事務隔離開來,防止資料損壞。

④、永續性(Durability):一旦事務完成,無論發生什麼系統錯誤,它的結果都不應該受到影響,這樣就能從任何系統崩潰中恢復過來。通常情況下,事務的結果被寫到持久化儲存器中。

三、平臺事務管理器(核心API:PlatformTransactionManager)

PlatformTransactionManager 事務管理器 Spring事務管理器的介面是org.springframework.transaction.PlatformTransactionManager,Spring並不直接管理事務,通過這個介面,Spring為各個平臺如JDBC、Hibernate等都提供了對應的事務管理器,也就是將事務管理的職責委託給Hibernate或者JTA等持久化機制所提供的相關平臺框架的事務來實現。

我們進入到 PlatformTransactionManager 介面,檢視原始碼:

①、TransactionStatus getTransaction(TransactionDefinition definition) ,事務管理器 通過TransactionDefinition,獲得“事務狀態”,從而管理事務。

②、void commit(TransactionStatus status)  根據狀態提交

③、void rollback(TransactionStatus status) 根據狀態回滾

也就是說Spring事務管理的為不同的事務API提供一致的程式設計模型,具體的事務管理機制由對應各個平臺去實現。

四、基本事務屬性的定義

那麼什麼是事務屬性呢?事務屬性可以理解成事務的一些基本配置,描述了事務策略如何應用到方法上。事務屬性包含了5個方面,如圖所示:

①傳播行為:

當事務方法被另一個事務方法呼叫時,必須指定事務應該如何傳播。

Spring 定義瞭如下七中傳播行為,這裡以A業務和B業務之間如何傳播事務為例說明:

  • PROPAGATION_REQUIRED :required , 必須。預設值,A如果有事務,B將使用該事務;如果A沒有事務,B將建立一個新的事務。
  • PROPAGATION_SUPPORTS:supports ,支援。A如果有事務,B將使用該事務;如果A沒有事務,B將以非事務執行。
  • PROPAGATION_MANDATORY:mandatory ,強制。A如果有事務,B將使用該事務;如果A沒有事務,B將拋異常。
  • PROPAGATION_REQUIRES_NEW :requires_new,必須新的。如果A有事務,將A的事務掛起,B建立一個新的事務;如果A沒有事務,B建立一個新的事務。
  • PROPAGATION_NOT_SUPPORTED :not_supported ,不支援。如果A有事務,將A的事務掛起,B將以非事務執行;如果A沒有事務,B將以非事務執行。
  • PROPAGATION_NEVER :never,從不。如果A有事務,B將拋異常;如果A沒有事務,B將以非事務執行。PROPAGATION_NESTED :nested ,巢狀。如果A當前存在事務,則在巢狀事務內執行。如果當前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作。

②隔離級別:

定義了一個事務可能受其他併發事務影響的程度。

在典型的應用程式中,多個事務併發執行,經常會操作相同的資料來完成各自的任務。併發雖然是必須的,但可能會導致以下的問題。

  • 髒讀(Dirty reads)——髒讀發生在一個事務讀取了另一個事務改寫但尚未提交的資料時。如果改寫在稍後被回滾了,那麼第一個事務獲取的資料就是無效的。
  • 不可重複讀(Nonrepeatable read)——不可重複讀發生在一個事務執行相同的查詢兩次或兩次以上,但是每次都得到不同的資料時。這通常是因為另一個併發事務在兩次查詢期間進行了更新。
  • 幻讀(Phantom read)——幻讀與不可重複讀類似。它發生在一個事務(T1)讀取了幾行資料,接著另一個併發事務(T2)插入了一些資料時。在隨後的查詢中,第一個事務(T1)就會發現多了一些原本不存在的記錄。

   注意:不可重複讀重點是修改,而幻讀重點是新增或刪除。

在 Spring 事務管理中,為我們定義瞭如下的隔離級別:

  • ISOLATION_DEFAULT:使用後端資料庫預設的隔離級別(不同的資料隔離級別不同)
  • ISOLATION_READ_UNCOMMITTED:最低的隔離級別,允許讀取尚未提交的資料變更,可能會導致髒讀、幻讀或不可重複讀
  • ISOLATION_READ_COMMITTEDOracle:允許讀取併發事務已經提交的資料,可以阻止髒讀,但是幻讀或不可重複讀仍有可能發生
  • ISOLATION_REPEATABLE_READmysql:對同一欄位的多次讀取結果都是一致的,除非資料是被本身事務自己所修改,可以阻止髒讀和不可重複讀,但幻讀仍有可能發生
  • ISOLATION_SERIALIZABLE:最高的隔離級別,完全服從ACID的隔離級別,確保阻止髒讀、不可重複讀以及幻讀,也是最慢的事務隔離級別,因為它通常是通過完全鎖定事務相關的資料庫表來實現的。

上面定義的隔離級別,在 Spring 的 TransactionDefinition.class 中也分別用常量 -1,1,2,4,8表示。比如 ISOLATION_DEFAULT 的定義:

③只讀:

這是事務的第三個特性,是否為只讀事務。如果事務只對後端的資料庫進行該操作,資料庫可以利用事務的只讀特性來進行一些特定的優化。通過將事務設定為只讀,你就可以給資料庫一個機會,讓它應用它認為合適的優化措施。

Spring會管理事務,但是查詢一般都設定成只讀事務,效能會高!

④事務超時:

為了使應用程式很好地執行,事務不能執行太長的時間。因為事務可能涉及對後端資料庫的鎖定,所以長時間的事務會不必要的佔用資料庫資源。事務超時就是事務的一個定時器,在特定時間內事務如果沒有執行完畢,那麼就會自動回滾,而不是一直等待其結束。

⑤回滾規則:

事務五邊形的最後一個方面是一組規則,這些規則定義了哪些異常會導致事務回滾而哪些不會。預設情況下,事務只有遇到執行期異常時才會回滾,而在遇到檢查型異常時不會回滾(這一行為與EJB的回滾行為是一致的) 。但是你可以宣告事務在遇到特定的檢查型異常時像遇到執行期異常那樣回滾。同樣,你還可以宣告事務遇到特定的異常不回滾,即使這些異常是執行期異常。

可以指定何種型別的異常是否需要回滾撤銷。

五、Spring程式設計式事務和宣告式事務的區別

①程式設計式事務

所謂程式設計式事務指的是通過編碼方式實現事務,允許使用者在程式碼中精確定義事務的邊界。即類似於JDBC程式設計實現事務管理。管理使用TransactionTemplate或者直接使用底層的PlatformTransactionManager。對於程式設計式事務管理,spring推薦使用TransactionTemplate。

②宣告式事務

管理建立在AOP之上的。其本質是對方法前後進行攔截,然後在目標方法開始之前建立或者加入一個事務,在執行完目標方法之後根據執行情況提交或者回滾事務。宣告式事務最大的優點就是不需要通過程式設計的方式管理事務,這樣就不需要在業務邏輯程式碼中摻雜事務管理的程式碼,只需在配置檔案中做相關的事務規則宣告(或通過基於@Transactional註解的方式),便可以將事務規則應用到業務邏輯中。

宣告式事務處理 基於XML配置

宣告式事務處理 基於註解配置

簡單地說,程式設計式事務侵入到了業務程式碼裡面,但是提供了更加詳細的事務管理;而宣告式事務由於基於AOP,所以既能起到事務管理的作用,又可以不影響業務程式碼的具體實現。

③程式設計式事務缺點

在實際應用中,很少需要通過程式設計來進行事務管理,即便如此,Spring還是為程式設計式事務管理提供了模板類 org.springframework.transaction.support.TransactionTemplate,以滿足一些特殊場合的需求!以滿足

一些特殊場合的需求.

TransactionTemplate和那些持久化模板類一樣是執行緒安全的,因此,可以在多個業務類中共享TranscationTemplate例項進行事務管理.TransactionTemplate擁有多個設定事務的屬性方法.如setReadOnly(boolean only), setIsolationLevel(int isolationLevel)等.

TransactionTemplate有兩個主要方法:

void setTransactionManager(PlatformTransactionManager transactionManager) 設定事務管理器.

Object execute(TransactionCallback action): 在TransactionCallback回撥介面中定義需要以事務方式組織的資料訪問邏輯.

TransactionCallback 介面只有一個方法: Object doInTransaction(TransactionStatus status).如果操作不會返回結果,則可以使用TransactionCallback的子介面 TransactionCallbackWithoutResult.