Spring 事務的隔離級別和傳播行為的理解
一、Spring 事務的隔離級別
在瞭解Spring事務隔離級別前,先弄清楚以下概念:
髒讀:髒讀發生在一個事務讀取了被另一個事務改寫但還未提交的資料時。如果這些改變在稍後被回滾,那麼之前的事務讀取的到資料就是無效的。
不可重複讀:不可重複讀發生在一個事務執行相同的查詢兩次或兩次以上,但每一次的查詢結果不同時。這通常是由於另一個併發的事務在兩次查詢之間更新了資料。
幻讀:幻讀是一個事務讀取幾行記錄後,另一個事務插入了一些記錄,幻讀就發生了。在後來的查詢中第一個事務就會發現有一些原來沒有的額外的記錄。
(1)ISOLATION_DEFAULT
使用資料的隔離級別
(2)ISOLATION_READ_UNCOMMITTED
允許讀取改變了的還未提交的資料,可能導致髒讀、不可重複讀和幻讀
(3)ISOLATION_READ_COMMITTED
允許併發事務提交之後讀取,可以避免髒讀,可能導致重複讀和幻讀
(4)ISOLATION_REPEATABLE_READ
對相同欄位的多次讀取結果一致,可導致幻讀
(5)ISOLATION_SERIALIZABLE
完全服從ACID的原則,確保不發生髒讀、不可重複讀和幻讀
二、Spring 事務的傳播行為
在瞭解Spring事務傳播行為前,先看一下程式碼:
@Service
public class ConsumerServiceImpl implements ConsumerService {
@Autowired
private ProviderService providerService;
@Transactional(propagation = ConsumerPropagation)
public void consume() {
provideBeforeCode;
providerService.provide();
provideAfterCode;
}
}
@Service
public class ProviderServiceImpl implements ProviderService {
@Transactional(propagation = ProviderPropagation)
public void provide() {
provideCode;
}
}
(1) PROPAGATION_REQUIRED
是Spring預設的傳播行為。 支援當前事務。如果不存在,則新建一個;如果存在,則加入當前事務中。> 所以,整個過程,Spring建立了一個事務,這個事務包含了所有內容。如以上程式碼,ConsumerPropagation為Propagation.REQUIRED,ConsumerPropagation為Propagation.REQUIRED,這樣的話provideBeforeCode;provideAfterCode;provideCode;會在同一個事務中,無論哪一塊程式碼發生執行時異常該事務都會回滾(Spring 預設發生執行時異常會回滾事務),即使provideCode發生執行時異常向外丟擲,且providerService.provide();被try catch,異常不丟擲,也會回滾,因為在provideCode發生執行時異常向外丟擲時,Spring會將該事務標記為robackOnly為true,即使異常沒有在consume丟擲,Spring在提交事務時,會報Transaction marked as rollbackOnly錯誤。
(2) PROPAGATION_REQUIRES_NEW
如果存在一個事務,則掛起當前事務,建立一個新的事務;如果不存在,則直接建立一個新的事務。
1> ConsumerPropagation為Propagation.REQUIRED,ConsumerPropagation為Propagation.REQUIRES_NEW;那麼provideBeforeCode;provideAfterCode;在一個事務中,provideCode;在另一個事務中;如果provideCode;發生執行時異常且向外丟擲,那麼provideCode;所處的事務將會回滾。如果providerService.provide();沒有被try catch,那麼provideBeforeCode;provideAfterCode;所處的事務也會回滾,如果providerService.provide();被try catch且沒有向外丟擲,那麼provideBeforeCode;provideAfterCode;所處的事務不會回滾。
2>ConsumerPropagation為Propagation.REQUIRED,ConsumerPropagation為Propagation.REQUIRES_NEW;如果provideAfterCode;發生執行時異常且向外丟擲,那麼provideBeforeCode;provideAfterCode;會被回滾,而provideCode;不會回滾;
(3) PROPAGATION_SUPPORTS
支援當前事務。如果不存在,則以非事務形式執行;如果存在,則加入當前事務中。
(4) PROPAGATION_NOT_SUPPORTED
不支援當前事務。如果不存在,則以非事務形式執行;如果存在,則掛起當前事務,以非事務形式執行,執行完畢後再恢復原事務繼續執行。
(5) PROPAGATION_MANDATORY
支援當前事務。如果不存在,則丟擲一個異常;如果存在,則加入當前事務中。
(6) PROPAGATION_NEVER
不支援當前事務。如果不存在,則以非事務形式執行;如果存在,則丟擲一個異常。
(7) PROPAGATION_NESTED
如果當前存在一個事務,則嵌入一個事務並執行;如果不存在一個事務,則新建一個事務並執行。