1. 程式人生 > >Spring 事務的隔離級別和傳播行為的理解

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

如果當前存在一個事務,則嵌入一個事務並執行;如果不存在一個事務,則新建一個事務並執行。