Spring事務詳解

2022-09-24 19:06:08 字數 4670 閱讀 5503

什麼叫事務?

關於事務,最簡單最常見的例子就是取錢。atm機取錢有兩個步驟,第一步輸入金額密碼,銀行卡扣掉1000元,第二步atm出鈔1000元,這兩個步驟必須要麼都執行成功,要麼都不執行。如果其中乙個步驟失敗了,必須把整個過程回滾,取消掉所有操作,這就是事務最基本的應用,事務就是用來解決類似問題的。

**舉例:

connection conn = drivermanager.getconnection();

try catch (exception e) finally

事務的四個特性(acid)

acid,指資料庫事務正確執行的四個基本要素的縮寫。包含:原子性(atomicity)、一致性(consistency)、隔離性(isolation)、永續性(durability)。

原子性整個事務中的所有操作,要麼全部完成,要麼全部不完成,不可能停滯在中間某個環節。事務在執行過程中發生錯誤,會被回滾(rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。

一致性乙個事務可以封裝狀態改變(除非它是乙個唯讀的)。事務必須始終保持系統處於一致的狀態,不管在任何給定的時間併發事務有多少。

也就是說:如果事務是併發多個,系統也必須如同序列事務一樣操作。其主要特徵是保護性和不變性(preserving an

invariant),以轉賬案例為例,假設有五個賬戶,每個賬戶餘額是100元,那麼五個賬戶總額是500元,如果在這個5個賬戶之間同時發生多個轉賬,無論併發多少個,比如在a與b賬戶之間轉賬5元,在c與d賬戶之間轉賬10元,在b與e之間轉賬15元,五個賬戶總額也應該還是500元,這就是保護性和不變性。

隔離性隔離狀態執行事務,使它們好像是系統在給定時間內執行的唯一操作。如果有兩個事務,執行在相同的時間內,執行相同的功能,事務的隔離性將確保每一事務在系統中認為只有該事務在使用系統。這種屬性有時稱為序列化,為了防止事務操作間的混淆,必須序列化或序列化請求,使得在同一時間僅有乙個請求用於同一資料。

永續性在事務完成以後,該事務對資料庫所作的更改便持久的儲存在資料庫之中,並不會被回滾。

由於一項操作通常會包含許多子操作,而這些子操作可能會因為硬體的損壞或其他因素產生問題,要正確實現acid並不容易。acid建議資料庫將所有需要更新以及修改的資料一次操作完畢,但實際上並不可行。

目前主要有兩種方式實現acid:第一種是write ahead

logging,也就是日誌式的方式(現代資料庫均基於這種方式)。第二種是shadow paging。

spring核心介面

spring並不直接管理事務,而是提供了多種事務管理器,他們將事務管理的職責委託給hibernate或者jta等持久化機制所提供的相關平台框架的事務來實現。

基本事務屬性的定義

傳播行為

隔離規則

回滾規則

事務超時

是否唯讀

傳播行為

傳播行為 含義

propagation_required 表示當前方法必須執行在事務中。如果當前事務存在,方法將會在該事務中執行。否則,會啟動乙個新的事務

propagation_supports 表示當前方法不需要事務上下文,但是如果存在當前事務的話,那麼該方法會在這個事務中執行

propagation_mandatory 表示該方法必須在事務中執行,如果當前事務不存在,則會丟擲乙個異常

propagation_required_new 表示當前方法必須執行在它自己的事務中。乙個新的事務將被啟動。如果存在當前事務,在該方法執行期間,當前事務會被掛起。

propagation_not_supported 表示該方法不應該執行在事務中。如果存在當前事務,在該方法執行期間,當前事務將被掛起。

propagation_never 表示當前方法不應該執行在事務上下文中。如果當前正有乙個事務在執行,則會丟擲異常。

propagation_nested 表示如果當前已經存在乙個事務,那麼該方法將會在巢狀事務中執行。巢狀的事務可以獨立於當前事務進行單獨地提交或回滾。如果當前事務不存在,那麼其行為與propagation_required一樣。

隔離規則

在企業級應用中,多使用者訪問資料庫是常見的場景,這就是所謂的事務的併發。事務併發所可能存在的問題:

1.髒讀:乙個事務讀到另乙個事務未提交的更新資料。

2.不可重複讀:乙個事務兩次讀同一行資料,可是這兩次讀到的資料不一樣。

3.幻讀:乙個事務執行兩次查詢,但第二次查詢比第一次查詢多出了一些資料行。

4.丟失更新:撤消乙個事務時,把其它事務已提交的更新的資料覆蓋了。

不可重複讀:事務1第一次查詢記錄a,事務2對記錄a進行修改並提交事務,事務1第二次查詢記錄a時發現兩次結果不一致,這就是不可重複讀。

幻讀:事務1第一次查詢表的總數量為b,事務2對錶增加了一條記錄,事務1第二次查詢表的總數量變成了b+1,兩次的結果也不一致,這是幻讀。

不可重複讀的重點是修改,幻讀的重點是插入和刪除;對於前者, 只需要鎖住滿足條件的記錄,對於後者, 要鎖住滿足條件及其相近的記錄。

隔離級別 含義

isolation_default 使用後端資料庫預設的隔離級別

isolation_read_uncommitted 最低的隔離級別,允許讀取尚未提交的資料變更,可能會導致髒讀、幻讀或不可重複讀

isolation_read_committed 允許讀取併發事務已經提交的資料,可以阻止髒讀,但是幻讀或不可重複讀仍有可能發生

isolation_repeatable_read 對同一欄位的多次讀取結果都是一致的,除非資料是被本身事務自己所修改,可以阻止髒讀和不可重複讀,但幻讀仍有可能發生

isolation_serializable 最高的隔離級別,完全服從acid的隔離級別,確保阻止髒讀、不可重複讀以及幻讀,也是最慢的事務隔離級別,因為它通常是通過完全鎖定事務相關的資料庫表來實現的

回滾規則

回滾規則定義了哪些異常會導致事務回滾而哪些不會。預設情況下,事務只有遇到執行期異常時才會回滾,而在遇到檢查型異常時不會回滾(這一行為與ejb的回滾行為是一致的)

但是你可以宣告事務在遇到特定的檢查型異常時像遇到執行期異常那樣回滾。同樣,你還可以宣告事務遇到特定的異常不回滾,即使這些異常是執行期異常。

事務超時

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

是否唯讀

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

註解方式的事務使用注意事項

正確的設定@transactional 的 propagation 屬性

需要注意下面三種 propagation 可以不啟動事務。如果期望對目標方法進行事務管理,但若是錯誤的配置這三種 propagation,事務將不會發生回滾。

transactiondefinition.propagation_supports:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續執行。

transactiondefinition.propagation_not_supported:以非事務方式執行,如果當前存在事務,則把當前事務掛起。

transactiondefinition.propagation_never:以非事務方式執行,如果當前存在事務,則丟擲異常。

正確的設定@transactional 的 rollbackfor 屬性

預設情況下,如果在事務中丟擲了未檢查異常(繼承自 runtimeexception 的異常)或者 error,則 spring 將回滾事務;除此之外,spring 不會回滾事務。

如果在事務中丟擲其他型別的異常,並期望 spring 能夠回滾事務,可以指定 rollbackfor。例:

@transactional(propagation= propagation.required,rollbackfor= myexception.class)

@transactional 只能應用到 public 方法才有效

只有@transactional 註解應用到 public 方法,才能進行事務管理。這是因為在使用 spring aop **時,abstractfallbacktransactionattributesource的 computetransactionattribute 方法會檢查目標方法的修飾符是不是 public,若不是 public,就不會獲取@transactional 的屬性配置資訊,最終會造成不會用 transactioninterceptor 來攔截該目標方法進行事務管理。

避免 spring 的 aop 的自呼叫問題

在 spring 的 aop **下,只有目標方法由外部呼叫,目標方法才由 spring 生成的**物件來管理,這會造成自呼叫問題。若同一類中的其他沒有@transactional 註解的方法內部呼叫有@transactional 註解的方法,有@transactional 註解的方法的事務被忽略,不會發生回滾。

@service

public class orderservice

@transactional

public void insertorder()

}insertorder 儘管有@transactional 註解,但它被內部方法 insert 呼叫,事務被忽略,出現異常事務不會發生回滾。

Spring事務詳解

事務傳播行為型別 說明propagation required 如果當前沒有事務,就新建乙個事務,如果已經存在乙個事務中,加入到這個事務中。這是最常見的選擇。propagation supports 支援當前事務,如果當前沒有事務,就以非事務方式執行。propagation mandatory 使用...

spring事務詳解

1.spring事務原理 spring事務的本質其實就是資料庫對事務的支援,沒有資料庫對事務的支援就無法提供事務的功能。2.spring事務傳播屬性 propagation required 支援當前事務,如果當前沒有事務,就新建乙個事務。這是最常見的選擇,也是 spring 預設的事務的傳播。pr...

Spring 事務機制詳解

spring事務機制主要包括宣告式事務和程式設計式事務,此處側重講解宣告式事務,程式設計式事務在實際開發中得不到廣泛使用,僅供學習參考。spring 宣告式事務讓我們從複雜的事務處理中得到解脫。使得我們再也無需要去處理獲得連線 關閉連線 事務提交和回滾等這些操作。再也無需要我們在與事務相關的方法中處...