(入門SpringBoot)SpringBoot項目事務(三)

     Spring聲明式事務的使用:@Transactional進行標註,可使用在類和方法上。當標註在類上,類下面全部公共非靜態的方法都將啓用事務功能。接下來,運行事務註解標註的方法,Spring的事務攔截器就會同時使用事務管理的方法開啓事務,而後將代碼織入Spring數據庫事務的流程中,若是發生異常,就會回滾,若是不發生異常,那麼就會提交事務。spring

  

spring事務流程圖(本身瞎畫的):sql

 

1.@Transactional源碼分析:
   timeout是事務能夠存在的時間戳.(單位爲秒)
   Value和transactionManager屬性是配置的一個Spring事務管理器.
   readOnly屬性定義事務是否只讀.
   rollbackFor,rollbackForClassName,noRollbackFor和noRollbackForClassName都是指定異常.發生什麼異常回滾事務.
   propagation傳播行爲.
   isolation隔離級別
2.隔離級別:
   關於隔離級別,先說一下數據庫事務的4個基本特徵,也就是ACID,也算是老話長談了,
原子性:(事務的操做是一個總體,要麼所有成功,要麼所有失敗,不會出現部分紅功,部分失敗.),
一致性:(事務在完成的時候,必須全部的數據都保持一致的狀態.),
隔離性:(不一樣事務操做的數據,互相不影響),
持久性:(事務執行事後,數據會存儲到數據庫中)
隔離級別解決的事情,舉個例子說明:
2.1.一個商品初始化爲2,事務一扣減庫存1,庫存爲1,事務2扣減庫存,讀取到事務1爲提交的庫存數據,扣減庫存1,提交事務,庫存保存爲0,事務一回滾事務,庫存結果爲0,結果錯誤.
未提交讀(read uncommitted)最低的隔離級別,容許一個事務度去另外一個事務沒有提交的數據.
    
   2.2.讀寫提交(read committed)隔離級別,是指定一個事務只能讀取另一個事務已經提交的數據,不能讀取未提交的數據.有效的解決了2.1.髒讀的問題.
      可是仍舊會出現下列問題:
      不可重讀場景:商品庫存初始化爲1,事務一讀取庫存1,扣減庫存,未提交,事務2讀取庫存1,認爲能夠扣減,此時事務一提交,庫存變爲0,事務2扣減庫存失敗,庫存爲0,沒法扣減.
      可重複讀:就是克服讀寫提交中出現的不可重複讀的狀況,由於在讀寫提交的時候,確實會出現一些值的變化.
      簡單點說,就是庫存已經被事務一先讀取,因此這個時候數據庫就阻塞它的讀取,直到事務一提交,事務2才能讀取庫存的值.
      幻讀:舉個例子,事務一讀取庫存50件貨,商品庫存初始化爲100,如今已經銷售了50,剩餘50,事務2讀取交易記錄50,事務一扣減庫存,插入交易記錄,提交事務,庫存49件,交易記錄51筆,事務2打印交易記錄51筆,這裏與查詢不一致,在事務2看來有1筆是虛幻的,與以前查詢不一致.
2.3.串行化(serializable),數據庫隔離最高級別,全部sql按順序執行.
提示:能夠在代碼中配置隔離級別.
# -1 數據庫默認隔離級別,
#1 未提交讀
#2 讀寫提交
#4 可重複讀
#8 串行化
# tomcat 數據源默認隔離級別:
Spring.datasource.tomcat.default-transaction-isolation=2
#dbcp2數據庫鏈接池默認隔離級別
Spring.datasource.dbcp2.default-transaction-isolation=2
3.傳播行爲:
  在Spring中當一個方法調用另一個方法時,可讓事務採起不一樣的策略工做。
  3.1.傳播行爲的定義:
  
  REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED):須要事務,它是默認的傳播行爲,若是當前存在事務,就用當前的事務,不然新建一個事務運行子方法.
 SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS):支持事務,若是當前存在事務,就用當前事務,若是不存在,就繼續採用無事務的方式運行子方法.
MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY):必須使用事務,若是當前沒有事務,就會拋出異常,若是存在當前事務,那麼就使用當前事務.
REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW):不管當前事務是否存在,都會建立新的事務執行方法,這樣新的事務就能夠擁有新的鎖和隔離級別的特性,與當前事務互相獨立.
NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED)不支持事務,當前存在事務,將掛起事務,運行方法.
NEVER(TransactionDefinition.PROPAGATION_NEVER)不支持事務,若是當前方法有事務,就拋出異常,不然繼續使用無事務機制運行.
NESTED(TransactionDefinition.PROPAGATION_NESTED)在當前方法調用子方法時候,若是子方法發生異常,只回滾子方法執行過的sql,而不會滾當前方法的事務.

3.2.@Transactional自調用失效的問題:
   類自身的調用是不會產生AOP的,解決方法可使用一個Service去調用另外一個Service,這樣就是代理對象的調用,Spring纔會將你的代碼,放入AOP.
相關文章
相關標籤/搜索