spring事務原理

1.  事務基本概念mysql

    事務是指在數據庫系統執行過程當中的一個邏輯單元,由有限的數據庫操做序列構成。spring

1.1 事務的基本特色sql

    事務具備四個屬性:ACID本別是: 原子性(atomicity)、一致性(consistency)、隔離性(isolation)、持久性(durability)。數據庫

    原子性(要麼成功要麼失敗):一個事務是不可分割的基本單位,事務中的全部操做要麼要麼所有都作,要麼所有不作。併發

    一致性(數據庫狀態變化):事務必須使數據庫從一個狀態變化到另外一個狀態。一致性與原子性密切相關。oracle

    隔離性(互不影響):一個事務的執行不能被其餘事務干擾。不一樣的事務之間互補干擾。性能

    持久性(不能撤銷):一個事務一旦提交,它對數據庫中數據的改變就是永久性的。atom

2. 事務的基本原理url

    spring事務的本質是對數據庫事務的支持,沒有數據庫事務的支持,spring是沒法提供事務功能的。spa

    對jdbc操做數據庫要使用事務,使用以下步驟:

    (1) 獲取鏈接 Connection con = DriverManager.getConnection(url,username,password);

    (2) 開啓事務 con.setAutoCommit(false);

    (3) 執行數據庫curd操做

    (4) 提交事務/回滾事務 con.commit()/con.rollback();

    (5) 關閉鏈接 conn.close();

    在是用spring的事務管理功能後,咱們能夠不用再寫2和4的代碼,而是由spring自動完成, 具體如何自動完成的,使用到了aop和動態代理的相關技術。

3. spring事務的傳播特性

    spring事務的傳播特性就是定義同時存在多個事務的時候,spring應該如何處理這些事務的行爲。

    這些屬性定義在TransactionDefinition中,具體常量解釋以下:

常量名稱 常量解釋
PROPAGATION_REQUIRED 支持當前事務,若是當前沒有事務就新建一個事務。這是最多見的選擇,也是spring默認的事務的傳播
PROPAGATION_REQUIRES_NEW 新建事務,若是當前存在事務,就把當前事務掛起。新建的事務和被掛起的事務是兩個獨立的事務,外層事務失敗回滾以後不能回滾內部事務執行的結果, 內存事務失敗拋出異常,外層事務捕獲,也能夠不處理回滾操做。
PROPAGATION_SUPPORTS 支持當前事務,若是當前沒有事務,就以非事務的方式運行
PROPAGATION_NOT_SUPPORTED 以非事務的方式運行,若是當前存在事務,就把當前事務掛起
PROPAGATION_MANDATORY 支持當前事務,若是當前沒有事務,就拋出異常
PROPAGATION_NEVER 以非事務的方式運行,若是當前存在事務,就拋出異常
PROPAGATION_NESTED 若是一個活動的事務存在,則運行在嵌套的事務中,若是沒有活動的事務,則按PROPAGATION_REQUIRED執行。使用一個單獨的事務,這個事務擁有多個能夠回滾的事務保存點。

4. 數據庫事務隔離級別      

    髒讀: 在一個事務中讀取到另外一個事務未提交的數據。

    不可重複度:在一個事務中兩次的查詢結果不同(針對update操做)。

    幻讀:在一個事務中兩次的查詢結果不同(正對insert操做)   

                            √ 可能出現 × 不會出現
隔離級別 髒讀 不可重複讀 幻讀
ISOLATION_READ_UNCOMMITED
ISOLATION_READ_COMMITED ×
ISOLATION_REPEATABLE_READ × ×
ISOLATION_SERIALIZABLE × × ×

ISOLATION_READ_UNCOMMITED:事務最低的隔離級別,它容許另一個事務看到當前事務未提交的數據。可能產生藏獨、不可重複度、幻讀。

ISOLATION_READ_COMMITED:另外一個事務不能讀取當前事務未提交的數據。

ISOLATION_REPEATABLE_READ:防止了髒讀、不可重複讀出現,可是可能出現幻讀。

ISOLATION_SERIALIZABLE:防止了髒讀、不可重複讀、幻讀,可靠性最好的事務級別,可是執行效率也是最慢的,慎用。

數據庫隔離級別越高,越能保證數據的完整性和一致性,可是對併發性能的影響也越大。多數數據的默認隔離級別都是read commited,如sqlServer,oracle;少數數據庫隔離級別默認是repeatable read,如mysqlInnoDB。

5. spring中的事務隔離級別

ISOLATION_DEFAULT spring默認的隔離級別,使用數據庫默認的隔離級別
ISOLATION_READ_UNCOMMITED 同數據庫事務隔離級別
ISLATION_READ_COMMITED 同數據庫事務隔離級別
ISOLATION_REPEATABLE_READ 同數據庫事務隔離級別
ISOLATION_SERIALIZEABLE 同數據庫事務隔離級別

6. 舉例說明事務的嵌套,理解spring事務傳播機制

假設外層事務serviceA的methodA()方法調用內層的serviceB的methodB()方法

PROPAGATION_REQUIRED

若是serviceB.methodB()的事務定義爲PROPAGATION_REQUIRED,若是servieA.methodA()執行的時候已經開啓了事務,那麼serviceB.methodB()在執行的時候發現已經在methodA的事務中,那麼就不會再新建一個事務;若是methodA()沒有在事務中,那麼methodB()在執行的時候就會新建一個事務。這樣在methodA()和methodB()中的任何地方出現異常,事務都會回滾,即便被methodA中catch住,也會由於是一個事物在methodB的時候標記爲事物失敗而拋出一個UnexpectedRollbackException(org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only)致使回滾。

PROPAGATION_REQUIRES_NEW

執行到method()的時候,methodA()所在的事務就會掛起,methodB()會新開啓一個事務,methodB()所在的事務執行完之後method所在的事務纔會繼續執行。它與PROPAGATION_REQUIRED的區別在於回滾的程度。由於B是新起的一個事務,若是B已經提交,A失敗回滾,那麼B也是不會回滾; 若是B失敗回滾,拋出的異常被A捕獲(try catch住),若是在catch中沒有拋出異常,那麼A不會回滾;若是catch中拋出異常而且是A上rollbackFor設置的異常,則回滾,若是不是,則不會回滾。

serviceA#methodA() -> serviceB#methodB()

若是methodB() 拋出異常,在methodA()中try catch住,若是沒有從新拋出或者拋出的異常不是methodA方法rollbackFor設置的異常,那麼 methodA 不會滾,methodB回滾;

若是methodB()拋出異常,在methodA()中try catch住,而且從新拋出了methodA上rollbackFor設置的異常,那麼methodA回滾,methodB回滾;

若是methodB()拋出異常,在methodA()中沒有try catch住,那麼methodA methodB都會回滾;

若是隻有methodA拋出異常,那麼methodA回滾,methodB不會滾

PROPAGATION_NESTED

serviceA#methodA() -> serviceB#methodB()

若是methodB()拋出異常,若是在methodA中catch處理,那麼methodA不會滾,methodB回滾;若是methodA沒有catch處理,那麼methodA,methodB都回滾

若是methodA()拋出異常,那麼methodA,methodB都回滾。

7. 對於同一個類中事物方法調用失效的狀況處理

首先須要設置exposeProxy=true, 經過xml方式或者註解方式:<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true" /> 或者 @EnableAspectJAutoProxy(exposeProxy=true)

調用:((UserService)AopContext.currentProxy()).testExpose1();

相關文章
相關標籤/搜索