天天看點

Spring五個事務隔離級别和七個事務傳播行為總結

Spring五個事務隔離級别:

Spring在TransactionDefinition接口中定義這些屬性

在TransactionDefinition接口中定義了五個不同的事務隔離級别

ISOLATION_DEFAULT 這是一個PlatfromTransactionManager預設的隔離級别,使用資料庫預設的事務隔離級别.另外四個與JDBC的隔離級别相對應 

注:Oracle資料庫預設的事物隔離級别已經保證了避免髒讀和不可重複讀。但可能會幻讀,避免幻讀需要加表級鎖,Oracle預設行級鎖。

ISOLATION_READ_UNCOMMITTED 這是事務最低的隔離級别,它充許别外一個事務可以看到這個事務未送出的資料。這種隔離級别會産生髒讀,不可重複讀和幻像讀

ISOLATION_READ_COMMITTED 保證一個事務修改的資料送出後才能被另外一個事務讀取。另外一個事務不能讀取該事務未送出的資料。這種事務隔離級别可以避免髒讀出現,但是可能會出現不可重複讀和幻像讀。通過對修改的行進行加鎖,避免髒讀。

  髒讀:髒讀就是指當一個事務正在通路資料,并且對資料進行了修改,而這種修改還沒有送出到資料庫中,這時,另外一個事務也通路這個資料,然後使用了這個資料。

ISOLATION_REPEATABLE_READ 這種事務隔離級别可以防止髒讀,不可重複讀。但是可能出現幻像讀。它除了保證一個事務不能讀取另一個事務未送出的資料外,還保證了避免下面的情況産生(不可重複讀)。通過對查詢所有的行進行加鎖,避免了不可重複讀。

   不可以重複讀:是指在一個事務内,多次讀同一資料。在這個事務還沒有結束時,另外一個事務也通路該同一資料。那麼,在第一個事務中的兩次讀資料之間,由于第二個事務的修改,那麼第一個事務兩次讀到的的資料可能是不一樣的。這樣就發生了在一個事務内兩次讀到的資料是不一樣的,是以稱為是不可重複讀。

ISOLATION_SERIALIZABLE 這是花費最高代價但是最可靠的事務隔離級别。事務被處理為順序執行。除了防止髒讀,不可重複讀外,還避免了幻像讀。通過對表加鎖實作。

 幻讀 :是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的資料進行了修改,這種修改涉及到表中的全部資料行。同時,第二個事務也修改這個表中的資料,這種修改是向表中插入一行新資料。那麼,以後就會發生操作第一個事務的使用者發現表中還有沒有修改的資料行,就好象發生了幻覺一樣。

在TransactionDefinition接口中定義了七個事務傳播行為。

事務是邏輯處理原子性的保證手段,通過使用事務控制,可以極大的避免出現邏輯處理失敗導緻的髒資料等問題。事務最重要的兩個特性,是事務的傳播級别和資料隔離級别。傳播級别定義的是事務的控制範圍,事務隔離級别定義的是事務在資料庫讀寫方面的控制範圍。

事務的7種傳播級别:

1)PROPAGATION_REQUIRED,預設的spring事務傳播級别,使用該級别的特點是,如果上下文中已經存在事務,那麼就加入到事務中執行,如果目前上下文中不存在事務,則建立事務執行。是以這個級别通常能滿足處理大多數的業務場景。

2)PROPAGATION_SUPPORTS,從字面意思就知道,supports,支援,該傳播級别的特點是,如果上下文存在事務,則支援事務加入事務,如果沒有事務,則使用非事務的方式執行。是以說,并非所有的包在transactionTemplate.execute中的代碼都會有事務支援。這個通常是用來處理那些并非原子性的非核心業務邏輯操作。應用場景較少。

3)PROPAGATION_MANDATORY,該級别的事務要求上下文中必須要存在事務,否則就會抛出異常!配置該方式的傳播級别是有效的控制上下文調用代碼遺漏添加事務控制的保證手段。比如一段代碼不能單獨被調用執行,但是一旦被調用,就必須有事務包含的情況,就可以使用這個傳播級别。

4)PROPAGATION_REQUIRES_NEW,從字面即可知道,new,每次都要一個新事務,該傳播級别的特點是,每次都會建立一個事務,并且同時将上下文中的事務挂起,執行目前建立事務完成以後,上下文事務恢複再執行。

這是一個很有用的傳播級别,舉一個應用場景:現在有一個發送100個紅包的操作,在發送之前,要做一些系統的初始化、驗證、資料記錄操作,然後發送100封紅包,然後再記錄發送日志,發送日志要求100%的準确,如果日志不準确,那麼整個父事務邏輯需要復原。

怎麼處理整個業務需求呢?就是通過這個PROPAGATION_REQUIRES_NEW級别的事務傳播控制就可以完成。發送紅包的子事務不會直接影響到父事務的送出和復原。

5)PROPAGATION_NOT_SUPPORTED,這個也可以從字面得知,not supported,不支援,目前級别的特點就是上下文中存在事務,則挂起事務,執行目前邏輯,結束後恢複上下文的事務。

這個級别有什麼好處?可以幫助你将事務極可能的縮小。我們知道一個事務越大,它存在的風險也就越多。是以在處理事務的過程中,要保證盡可能的縮小範圍。比如一段代碼,是每次邏輯操作都必須調用的,比如循環1000次的某個非核心業務邏輯操作。這樣的代碼如果包在事務中,勢必造成事務太大,導緻出現一些難以考慮周全的異常情況。是以這個事務這個級别的傳播級别就派上用場了。用目前級别的事務模闆抱起來就可以了。

6)PROPAGATION_NEVER,該事務更嚴格,上面一個事務傳播級别隻是不支援而已,有事務就挂起,而PROPAGATION_NEVER傳播級别要求上下文中不能存在事務,一旦有事務,就抛出runtime異常,強制停止執行!這個級别上輩子跟事務有仇。

7)PROPAGATION_NESTED,字面也可知道,nested,嵌套級别事務。該傳播級别特征是,如果上下文中存在事務,則嵌套事務執行,如果不存在事務,則建立事務。

事務常用的兩個屬性:readonly和timeout

readonly 是設定事務為隻讀以提升性能。“隻讀事務”并不是一個強制選項,它隻是一個“暗示”,提示資料庫驅動程式和資料庫系統,這個事務并不包含更改資料的操作,那麼JDBC驅動程式和資料庫就有可能根據這種情況對該事務進行一些特定的優化,比方說不安排相應的資料庫鎖,以減輕事務對資料庫的壓力,畢竟事務也是要消耗資料庫的資源的。 但是你非要在“隻讀事務”裡面修改資料,也并非不可以,隻不過對于資料一緻性的保護不像“讀寫事務”那樣保險而已。 是以,“隻讀事務”僅僅是一個性能優化的推薦配置而已,并非強制你要這樣做不可

timeout:是設定事務的逾時時間,一般用于防止大事務的發生。還是那句話,事務要盡可能的小!

spring配置檔案中關于事務配置總是由三個組成部分,分别是DataSource、TransactionManager和代理機制這三部分,無論哪種配置方式,一般變化的隻是代理機制這部分。

    DataSource、TransactionManager這兩部分隻是會根據資料通路方式有所變化,比如使用Hibernate進行資料通路時,DataSource實際為SessionFactory,TransactionManager的實作為 HibernateTransactionManager。

根據代理機制的不同,Spring事務的配置又有幾種不同的方式:

第一種方式:每個Bean都有一個代理

 第二種方式:所有Bean共享一個代理基類

第三種方式:使用攔截器

第四種方式:使用tx标簽配置的攔截器

第五種方式:全注解

1、spring事務控制放在service層,在service方法中一個方法調用service中的另一個方法,預設開啟幾個事務?

spring的事務傳播方式預設是PROPAGATION_REQUIRED,判斷目前是否已開啟一個新事務,有則加入目前事務,否則新開一個事務(如果沒有就開啟一個新事務),是以答案是開啟了一個事務。

2、spring什麼情況下進行事務復原?

Spring、EJB的聲明式事務預設情況下都是在抛出uncheckedexception後才會觸發事務的復原

unchecked異常,即運作時異常runntimeException復原事務;

checked異常,即Exception可try{}捕獲的不會復原.當然也可配置spring參數讓其復原.

spring的事務邊界是在調用業務方法之前開始的,業務方法執行完畢之後來執行commit or rollback(Spring預設取決于是否抛出runtime異常).

如果抛出runtime exception并在你的業務方法中沒有catch到的話,事務會復原。

一般不需要在業務方法中catch異常,如果非要catch,在做完你想做的工作後(比如關閉檔案等)一定要抛出runtime exception,否則spring會将你的操作commit,這樣就會産生髒資料.是以你的catch代碼是畫蛇添足。

事務配置注意:

 1:類内部方法調用時,被調用方法的事務聲明将不起作用

  2、:再換句話說,Spring的事務傳播政策在内部方法調用時将不起作用。不管你希望某個方法需要單獨事務,是RequiresNew,還是要嵌套事務,要Nested,等等,統統不起作用。

  3:不僅僅是事務通知,所有你自己利用Spring實作的AOP通知,都會受到同樣限制。。。。

如何提高并發效率

  1. 悲觀鎖:利用資料庫本身的鎖機制實作。通過上面對資料庫鎖的了解,可以根據具體業務情況綜合使用事務隔離級别與合理的手工指定鎖的方式比如降低鎖的粒度等減少并發等待。
  2. 樂觀鎖:利用程式處理并發。原理都比較好了解,基本一看即懂。方式大概有以下3種
    1. 對記錄加版本号.
    2. 對記錄加時間戳.
    3. 對将要更新的資料進行提前讀取、事後對比。

繼續閱讀