spring的事務傳播行為、隔離級別和事務的一些基本概念
阿新 • • 發佈:2018-12-25
事務ACID: 原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、永續性(Durability)。
1. 原子性(Atomicity): 原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生。
2. 一致性(Consistency): 事務必須使資料庫從一個一致性狀態變換到另外一個一致性狀態。
事務的一致性決定了一個系統設計和實現的複雜度。事務可以不同程度的一致性:
強一致性:讀操作可以立即讀到提交的更新操作。
弱一致性:提交的更新操作,不一定立即會被讀操作讀到,此種情況會存在一個不一致視窗,指的是讀操作可以讀到最新值的一段時間。
最終一致性:是弱一致性的特例。事務更新一份資料,最終一致性保證在沒有其他事務更新同樣的值的話,最終所有的事務都會讀到之前事務更新的最新值。如果沒有錯誤發生,不一致視窗的大小依賴於:通訊延遲,系統負載等。
其他一致性變體還有:
單調一致性:如果一個程序已經讀到一個值,那麼後續不會讀到更早的值。
會話一致性:保證客戶端和伺服器互動的會話過程中,讀操作可以讀到更新操作後的最新值。
3. 隔離性(Isolation): 事務的隔離性是指一個事務的執行不能被其他事務干擾,即一個事務內部的操作及使用的資料對併發的其他事務是隔離的,併發執行的各個事務之間不能互相干擾。
4. 永續性(Durability): 永續性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的,接下來的其他操作和資料庫故障不應該對其有任何影響。
在service類前加上@Transactional,宣告這個service所有方法需要事務管理。每一個業務方法開始時都會開啟一個事務。
Spring預設情況下會對執行期例外(RunTimeException)進行事務回滾。這個例外是unchecked
如果遇到checked意外就不回滾。
如何改變預設規則:
1 讓checked例外也回滾:在整個方法前加上 @Transactional(rollbackFor=Exception.class)
2 讓unchecked例外不回滾: @Transactional(notRollbackFor=RunTimeException.class)
3 不需要事務管理的(只查詢的)方法:@Transactional(propagation=Propagation.NOT_SUPPORTED)
在整個方法執行前就不會開啟事務
還可以加上:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true),這樣就做成一個只讀事務,可以提高效率。
各種屬性的意義:
REQUIRED:業務方法需要在一個容器裡執行。如果方法執行時,已經處在一個事務中,那麼加入到這個事務,否則自己新建一個新的事務。
NOT_SUPPORTED:宣告方法不需要事務。如果方法沒有關聯到一個事務,容器不會為他開啟事務,如果方法在一個事務中被呼叫,該事務會被掛起,呼叫結束後,原先的事務會恢復執行。
REQUIRESNEW:不管是否存在事務,該方法總彙為自己發起一個新的事務。如果方法已經執行在一個事務中,則原有事務掛起,新的事務被建立。
MANDATORY:該方法只能在一個已經存在的事務中執行,業務方法不能發起自己的事務。如果在沒有事務的環境下被呼叫,容器丟擲例外。
SUPPORTS:該方法在某個事務範圍內被呼叫,則方法成為該事務的一部分。如果方法在該事務範圍外被呼叫,該方法就在沒有事務的環境下執行。
NEVER:該方法絕對不能在事務範圍內執行。如果在就拋例外。只有該方法沒有關聯到任何事務,才正常執行。
NESTED:如果一個活動的事務存在,則執行在一個巢狀的事務中。如果沒有活動事務,則按REQUIRED屬性執行。它使用了一個單獨的事務,這個事務擁有多個可以回滾的儲存點。內部事務的回滾不會對外部事務造成影響。它只對DataSourceTransactionManager事務管理器起效。
在一個典型的應用中,併發是不可避免的,多個事務併發執行,操作同一個資料來完成任務。併發可能會導致以下問題:
髒讀(Dirty read):髒讀發生在一個事務讀取了被另一個事務改寫但還未提交的資料時。如果這些改變在稍後被回滾,那麼之前的事務讀取的到資料就是無效的。
不可重複讀(Nonrepeatable read):不可重複讀發生在一個事務執行相同的查詢兩次或兩次以上,但每一次的查詢結果不同時。這通常是由於另一個併發的事務在兩次查詢之間更新了資料。
幻讀(Phantom read):幻讀是一個事務讀取幾行記錄後,另一個事務插入了一些記錄,幻讀就發生了。在後來的查詢中第一個事務就會發現有一些原來沒有的額外的記錄。
spring的事務隔離級別
ISOLATION_DEFAULT:使用資料庫預設的隔離級別。
ISOLATION_READ_UNCOMMITTED:允許讀取改變了的還未提交的資料,可能導致髒讀、不可重複讀和幻讀。
ISOLATION_READ COMMITTED:允許併發事務提交之後讀取,可以避免髒讀,可能導致重複讀和幻讀。
ISOLATION_REPEATABLE_READ:對相同欄位的多次讀取結果一致,可導致幻讀。
ISOLATION_SERIALIZABLE:完全服從ACID的原則,確保不發生髒讀、不可重複讀和幻讀。
Dirty reads non-repeatable reads phantom reads
Serializable 不會 不會 不會
REPEATABLE READ 不會 不會 會
READ COMMITTED 不會 會 會
Read Uncommitted 會 會 會
spring的事務傳播行為
spring事務的傳播行為說的是當一個方法呼叫另一個方法時,事務該如何操作。
PROPAGATION_MANDATORY:該方法必須執行在一個事務中。如果當前事務不存在則丟擲異常。
PROPAGATION_NESTED:如果當前存在一個事務,則該方法執行在一個巢狀的事務中。被巢狀的事務可以從當前事務中單獨的提交和回滾。如果當前不存在事務,則開始一個新的事務。各廠商對這種傳播行為的支援參差不齊,使用時需注意。
PROPAGATION_NEVER:當前方法不應該執行在一個事務中。如果當前存在一個事務,則丟擲異常。
PROPAGATION_NOT_SUPPORTED:當前方法不應該執行在一個事務中。如果一個事務正在執行,它將在該方法的執行期間掛起。
PROPAGATION_REQUIRED:該方法必須執行在一個事務中。如果一個事務正在執行,該方法將執行在這個事務中。否則,就開始一個新的事務。
PROPAGATION_REQUIRES_NEW:該方法必須執行在自己的事務中。它將啟動一個新的事務。如果一個現有的事務正在執行,將在這個方法的執行期間掛起。
PROPAGATION_SUPPORTS:當前方法不需要事務處理環境,但如果一個事務已經在執行的話,這個方法也可以在這個事務裡執行。
宣告式:
使用TransactionProxyFactoryBean:
1. 原子性(Atomicity): 原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生。
2. 一致性(Consistency): 事務必須使資料庫從一個一致性狀態變換到另外一個一致性狀態。
事務的一致性決定了一個系統設計和實現的複雜度。事務可以不同程度的一致性:
強一致性:讀操作可以立即讀到提交的更新操作。
弱一致性:提交的更新操作,不一定立即會被讀操作讀到,此種情況會存在一個不一致視窗,指的是讀操作可以讀到最新值的一段時間。
最終一致性:是弱一致性的特例。事務更新一份資料,最終一致性保證在沒有其他事務更新同樣的值的話,最終所有的事務都會讀到之前事務更新的最新值。如果沒有錯誤發生,不一致視窗的大小依賴於:通訊延遲,系統負載等。
其他一致性變體還有:
單調一致性:如果一個程序已經讀到一個值,那麼後續不會讀到更早的值。
會話一致性:保證客戶端和伺服器互動的會話過程中,讀操作可以讀到更新操作後的最新值。
3. 隔離性(Isolation): 事務的隔離性是指一個事務的執行不能被其他事務干擾,即一個事務內部的操作及使用的資料對併發的其他事務是隔離的,併發執行的各個事務之間不能互相干擾。
4. 永續性(Durability): 永續性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的,接下來的其他操作和資料庫故障不應該對其有任何影響。
在service類前加上@Transactional,宣告這個service所有方法需要事務管理。每一個業務方法開始時都會開啟一個事務。
Spring預設情況下會對執行期例外(RunTimeException)進行事務回滾。這個例外是unchecked
如果遇到checked意外就不回滾。
如何改變預設規則:
1 讓checked例外也回滾:在整個方法前加上 @Transactional(rollbackFor=Exception.class)
2 讓unchecked例外不回滾: @Transactional(notRollbackFor=RunTimeException.class)
3 不需要事務管理的(只查詢的)方法:@Transactional(propagation=Propagation.NOT_SUPPORTED)
在整個方法執行前就不會開啟事務
還可以加上:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true),這樣就做成一個只讀事務,可以提高效率。
各種屬性的意義:
REQUIRED:業務方法需要在一個容器裡執行。如果方法執行時,已經處在一個事務中,那麼加入到這個事務,否則自己新建一個新的事務。
NOT_SUPPORTED:宣告方法不需要事務。如果方法沒有關聯到一個事務,容器不會為他開啟事務,如果方法在一個事務中被呼叫,該事務會被掛起,呼叫結束後,原先的事務會恢復執行。
REQUIRESNEW:不管是否存在事務,該方法總彙為自己發起一個新的事務。如果方法已經執行在一個事務中,則原有事務掛起,新的事務被建立。
MANDATORY:該方法只能在一個已經存在的事務中執行,業務方法不能發起自己的事務。如果在沒有事務的環境下被呼叫,容器丟擲例外。
SUPPORTS:該方法在某個事務範圍內被呼叫,則方法成為該事務的一部分。如果方法在該事務範圍外被呼叫,該方法就在沒有事務的環境下執行。
NEVER:該方法絕對不能在事務範圍內執行。如果在就拋例外。只有該方法沒有關聯到任何事務,才正常執行。
NESTED:如果一個活動的事務存在,則執行在一個巢狀的事務中。如果沒有活動事務,則按REQUIRED屬性執行。它使用了一個單獨的事務,這個事務擁有多個可以回滾的儲存點。內部事務的回滾不會對外部事務造成影響。它只對DataSourceTransactionManager事務管理器起效。
在一個典型的應用中,併發是不可避免的,多個事務併發執行,操作同一個資料來完成任務。併發可能會導致以下問題:
髒讀(Dirty read):髒讀發生在一個事務讀取了被另一個事務改寫但還未提交的資料時。如果這些改變在稍後被回滾,那麼之前的事務讀取的到資料就是無效的。
不可重複讀(Nonrepeatable read):不可重複讀發生在一個事務執行相同的查詢兩次或兩次以上,但每一次的查詢結果不同時。這通常是由於另一個併發的事務在兩次查詢之間更新了資料。
幻讀(Phantom read):幻讀是一個事務讀取幾行記錄後,另一個事務插入了一些記錄,幻讀就發生了。在後來的查詢中第一個事務就會發現有一些原來沒有的額外的記錄。
spring的事務隔離級別
ISOLATION_DEFAULT:使用資料庫預設的隔離級別。
ISOLATION_READ_UNCOMMITTED:允許讀取改變了的還未提交的資料,可能導致髒讀、不可重複讀和幻讀。
ISOLATION_READ COMMITTED:允許併發事務提交之後讀取,可以避免髒讀,可能導致重複讀和幻讀。
ISOLATION_REPEATABLE_READ:對相同欄位的多次讀取結果一致,可導致幻讀。
ISOLATION_SERIALIZABLE:完全服從ACID的原則,確保不發生髒讀、不可重複讀和幻讀。
Dirty reads non-repeatable reads phantom reads
Serializable 不會 不會 不會
REPEATABLE READ 不會 不會 會
READ COMMITTED 不會 會 會
Read Uncommitted 會 會 會
spring的事務傳播行為
spring事務的傳播行為說的是當一個方法呼叫另一個方法時,事務該如何操作。
PROPAGATION_MANDATORY:該方法必須執行在一個事務中。如果當前事務不存在則丟擲異常。
PROPAGATION_NESTED:如果當前存在一個事務,則該方法執行在一個巢狀的事務中。被巢狀的事務可以從當前事務中單獨的提交和回滾。如果當前不存在事務,則開始一個新的事務。各廠商對這種傳播行為的支援參差不齊,使用時需注意。
PROPAGATION_NEVER:當前方法不應該執行在一個事務中。如果當前存在一個事務,則丟擲異常。
PROPAGATION_NOT_SUPPORTED:當前方法不應該執行在一個事務中。如果一個事務正在執行,它將在該方法的執行期間掛起。
PROPAGATION_REQUIRED:該方法必須執行在一個事務中。如果一個事務正在執行,該方法將執行在這個事務中。否則,就開始一個新的事務。
PROPAGATION_REQUIRES_NEW:該方法必須執行在自己的事務中。它將啟動一個新的事務。如果一個現有的事務正在執行,將在這個方法的執行期間掛起。
PROPAGATION_SUPPORTS:當前方法不需要事務處理環境,但如果一個事務已經在執行的話,這個方法也可以在這個事務裡執行。
宣告式:
使用TransactionProxyFactoryBean: