事務的知識總結一下舵变,參考的文章如下:
https://www.open-open.com/lib/view/open1350865116821.html
http://www.blogjava.net/robbie/archive/2009/04/05/264003.html
https://www.jb51.net/article/57589.htm
初步理解
理解事務之前,先講一個你日常生活中最常干的事:取錢。
比如你去ATM機取1000塊錢,大體有兩個步驟:首先輸入密碼金額,銀行卡扣掉1000元錢乒省;然后ATM出1000元錢。這兩個步驟必須是要么都執(zhí)行要么都不執(zhí)行畦木。如果銀行卡扣除了1000塊但是ATM出錢失敗的話袖扛,你將會損失1000元;如果銀行卡扣錢失敗但是ATM卻出了1000塊十籍,那么銀行將損失1000元蛆封。所以,如果一個步驟成功另一個步驟失敗對雙方都不是好事勾栗,如果不管哪一個步驟失敗了以后惨篱,整個取錢過程都能回滾,也就是完全取消所有操作的話围俘,這對雙方都是極好的砸讳。
事務就是用來解決類似問題的琢融。事務是一系列的動作,它們綜合在一起才是一個完整的工作單元簿寂,這些動作必須全部完成漾抬,如果有一個失敗的話,那么事務就會回滾到最開始的狀態(tài)陶耍,仿佛什么都沒發(fā)生過一樣奋蔚。
在企業(yè)級應用程序開發(fā)中,事務管理必不可少的技術烈钞,用來確保數(shù)據(jù)的完整性和一致性泊碑。
事務有四個特性:ACID
原子性(Atomicity):事務是一個原子操作,由一系列動作組成毯欣。事務的原子性確保動作要么全部完成馒过,要么完全不起作用。
一致性(Consistency):一旦事務完成(不管成功還是失斝锍)腹忽,系統(tǒng)必須確保它所建模的業(yè)務處于一致的狀態(tài),而不會是部分完成部分失敗砚作。在現(xiàn)實中的數(shù)據(jù)不應該被破壞窘奏。
隔離性(Isolation):可能有許多事務會同時處理相同的數(shù)據(jù),因此每個事務都應該與其他事務隔離開來葫录,防止數(shù)據(jù)損壞着裹。
持久性(Durability):一旦事務完成,無論發(fā)生什么系統(tǒng)錯誤米同,它的結果都不應該受到影響骇扇,這樣就能從任何系統(tǒng)崩潰中恢復過來。通常情況下面粮,事務的結果被寫到持久化存儲器中少孝。
Spring事務管理的實現(xiàn)有許多細節(jié),如果對整個接口框架有個大體了解會非常有利于我們理解事務熬苍,下面通過講解Spring的事務接口來了解Spring實現(xiàn)事務的具體策略稍走。
Spring事務管理涉及的接口的聯(lián)系如下:
2.1 事務管理器
Spring并不直接管理事務,而是提供了多種事務管理器柴底,他們將事務管理的職責委托給hibernate或者JTA等持久化機制所提供的相關平臺框架的事務來實現(xiàn)婿脸。
Spring事務管理器的接口是org.springframework.transaction.PlatformTransactionManager,通過這個接口似枕,Spring為各個平臺如JDBC盖淡、Hibernate等都提供了對應的事務管理器,但是具體的實現(xiàn)就是各個平臺自己的事情了凿歼。此接口的內(nèi)容如下:
Public interfacePlatformTransactionManager()...{
// 由TransactionDefinition得到TransactionStatus對象
TransactionStatusgetTransaction(TransactionDefinition definition)throwsTransactionException;
// 提交
Voidcommit(TransactionStatus status)throwsTransactionException;
// 回滾
Voidrollback(TransactionStatus status)throwsTransactionException;
? ? }
從這里可知具體的具體的事務管理機制對Spring來說是透明的褪迟,它并不關心那些冗恨,那些是對應各個平臺需要關心的,所以Spring事務管理的一個優(yōu)點就是為不同的事務API提供一致的編程模型味赃,如JTA掀抹、JDBC、Hibernate心俗、JPA傲武。下面分別介紹各個平臺框架實現(xiàn)事務管理的機制。
2.2 基本事務屬性的定義
上面講到的事務管理器接口PlatformTransactionManager通過getTransaction(TransactionDefinition definition)方法來得到事務城榛,這個方法里面的參數(shù)是TransactionDefinition類揪利,這個類就定義了一些基本的事務屬性。
那么什么是事務屬性呢狠持?事務屬性可以理解成事務的一些基本配置疟位,描述了事務策略如何應用到方法上。事務屬性包含了5個方面喘垂,如圖所示:
2.2.1 傳播行為
事務的第一個方面是傳播行為(propagation behavior)甜刻。當事務方法被另一個事務方法調(diào)用時,必須指定事務應該如何傳播正勒。例如:方法可能繼續(xù)在現(xiàn)有事務中運行得院,也可能開啟一個新事務,并在自己的事務中運行章贞。Spring定義了七種傳播行為:
注:以下具體講解傳播行為的內(nèi)容參考自Spring事務機制詳解?
1:PROPAGATION_REQUIRED :當前方法必須運行在事務中祥绞。如果當前事務存在,方法將會在該事務中運行阱驾。否則就谜,會啟動一個新的事務
描述:單獨調(diào)用方法B時怪蔑,只是對B方法內(nèi)進行事務控制里覆,例如:
當通過調(diào)用方法A(配置事務控制)時,A中配置有PROPAGATION_REQUIRED類別缆瓣,方法A中調(diào)用方法B喧枷,B中同樣配置PROPAGATION_REQUIRED事務,根據(jù)PROPAGATION_REQUIRED的屬性弓坞,方法B對數(shù)據(jù)庫的操作會加入到方法A中隧甚,方法B捕獲異常,A會進行回滾渡冻。
2.PROPAGATION_SUPPORTS:如果存在一個事務戚扳,支持當前事務。如果沒有事務族吻,則非事務的執(zhí)行帽借。
描述:單純的調(diào)用methodB時珠增,methodB方法是非事務的執(zhí)行的,當通過方法A調(diào)用時砍艾,如果方法A配置事務控制蒂教,methodB則加入了methodA的事務中,事務地執(zhí)行,方法B捕獲異常脆荷,A會進行回滾凝垛。
3.PROPAGATION_REQUIRES_NEW 總是開啟一個新的事務。如果一個事務已經(jīng)存在蜓谋,則將這個存在的事務掛起
描述:單獨調(diào)用B時梦皮,會自動創(chuàng)建一個事務進行操作,通過方法A調(diào)用B是桃焕,A配置PROPAGATION_REQUIRED事務届氢。方法B配置PROPAGATION_REQUIRES_NEW?事務,當執(zhí)行B時覆旭,會把方法A的事務先掛起退子,當B進行完后,再提交A的事務型将。
4.PROPAGATION_NOT_SUPPORTED 總是非事務地執(zhí)行寂祥,并掛起任何存在的事務。
//事務屬性 PROPAGATION_REQUIRED
methodA(){
? ? methodB();
}
//事務屬性PROPAGATION_NOT_SUPPORTED
methodB(){
}
描述:單獨調(diào)用B時七兜,非事務進行操作丸凭,通過方法A調(diào)用B是,A配置PROPAGATION_REQUIRED事務腕铸。方法B配置PROPAGATION_NOT_SUPPORTED?事務惜犀,當執(zhí)行B時,會把方法A的事務先掛起狠裹,當B進行完后虽界,再提交A的事務。
5.PROPAGATION_NEVER 總是非事務地執(zhí)行涛菠,如果存在一個活動事務莉御,則拋出異常。
6.PROPAGATION_NESTED? 如果一個活動的事務存在俗冻,則運行在一個嵌套的事務中. 如果沒有活動事務, 則按TransactionDefinition.PROPAGATION_REQUIRED 屬性執(zhí)行礁叔。
描述:如果單獨調(diào)用methodB方法,則按REQUIRED屬性執(zhí)行迄薄,如果調(diào)用A琅关,相當于下面的效果:
當methodB方法調(diào)用之前,調(diào)用setSavepoint方法讥蔽,保存當前的狀態(tài)到savepoint涣易。如果methodB方法調(diào)用失敗人乓,則恢復到之前保存的狀態(tài)。但是需要注意的是都毒,這時的事務并沒有進行提交色罚,如果后續(xù)的代碼(doSomeThingB()方法)調(diào)用失敗,則回滾包括methodB方法的所有操作账劲。
嵌套事務一個非常重要的概念就是內(nèi)層事務依賴于外層事務戳护。外層事務失敗時,會回滾內(nèi)層事務所做的動作瀑焦。而內(nèi)層事務操作失敗并不會引起外層事務的回滾腌且。
PROPAGATION_NESTED 與PROPAGATION_REQUIRES_NEW的區(qū)別:它們非常類似,都像一個嵌套事務,如果不存在一個活動的事務榛瓮,都會開啟一個新的事務铺董。使用 PROPAGATION_REQUIRES_NEW時,內(nèi)層事務與外層事務就像兩個獨立的事務一樣禀晓,一旦內(nèi)層事務進行了提交后瓣喊,外層事務不能對其進行回滾茉帅。兩個事務互不影響雹仿。兩個事務不是一個真正的嵌套事務勺像。同時它需要JTA事務管理器的支持。
使用PROPAGATION_NESTED時凫乖,外層事務的回滾可以引起內(nèi)層事務的回滾确垫。而內(nèi)層事務的異常并不會導致外層事務的回滾,它是一個真正的嵌套事務帽芽。DataSourceTransactionManager使用savepoint支持PROPAGATION_NESTED時删掀,需要JDBC 3.0以上驅動及1.4以上的JDK版本支持。其它的JTA TrasactionManager實現(xiàn)可能有不同的支持方式导街。
PROPAGATION_REQUIRES_NEW 啟動一個新的, 不依賴于環(huán)境的 “內(nèi)部” 事務. 這個事務將被完全 commited 或 rolled back 而不依賴于外部事務, 它擁有自己的隔離范圍, 自己的鎖, 等等. 當內(nèi)部事務開始執(zhí)行時, 外部事務將被掛起, 內(nèi)務事務結束時, 外部事務將繼續(xù)執(zhí)行披泪。
另一方面, PROPAGATION_NESTED 開始一個 “嵌套的” 事務, 它是已經(jīng)存在事務的一個真正的子事務. 潛套事務開始執(zhí)行時, 它將取得一個 savepoint. 如果這個嵌套事務失敗, 我們將回滾到此 savepoint. 潛套事務是外部事務的一部分, 只有外部事務結束后它才會被提交。
由此可見, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大區(qū)別在于, PROPAGATION_REQUIRES_NEW 完全是一個新的事務, 而 PROPAGATION_NESTED 則是外部事務的子事務, 如果外部事務 commit, 嵌套事務也會被 commit, 這個規(guī)則同樣適用于 roll back.
PROPAGATION_REQUIRED應該是我們首先的事務傳播行為菊匿。它能夠滿足我們大多數(shù)的事務需求付呕。