1. 程式人生 > >spring的事務傳播行為、隔離級別和事務的一些基本概念

spring的事務傳播行為、隔離級別和事務的一些基本概念

事務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: