Spring事務-'後悔藥'

歡迎大家來我的個人博客:https://www.fxyh97.com/index.php/archives/273/

事務是啥,我覺得它是一個後悔藥,就是提供給程序一個後悔的機制,出錯了的時候可以後悔用的。

說到事務,當然得說四個特性(ACID)嘍

  1. 原子性(Atomicity)
    事務最基本的操作單元,要麼全部成功,要麼全部失敗,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被回滾到事務開始前的狀態,就像這個事務從來沒有執行過一樣。(就比如張三往李四轉賬了50萬,這時候要從張三帳號上扣除50萬,然後在李四賬號上加上50萬,這兩個操作要麼全部執行成功,要麼就全部失敗,不可能出現張三扣了錢李四上錢沒充值成功,或者張三扣除錢失敗,李四上充值成功的結果。這時候這個操作就相當於一個原子性的操作,不能再細分了。)

  2. 一致性(Consistency)
    事務的一致性指的是在一個事務執行之前和執行之後數據之間的關係都必須處於一致性狀態。(就比如一個銀行一共有100萬(張三帳號上有100萬,李四帳號上爲0元),張三往李四在這個銀行的賬戶上轉賬了50萬,那張三就還有50萬,李四也有50萬,這個銀行的所有帳戶加起來就一定是100萬,如果不是100萬就不一致了。)

  3. 隔離性(Isolation)
    指的是在併發環境中,當不同的事務同時操縱相同的數據時,每個事務都有各自的完整數據空間。由併發事務所做的修改必須與任何其他併發事務所做的修改隔離。事務查看數據更新時,數據所處的狀態要麼是另一事務修改它之前的狀態,要麼是另一事務修改它之後的狀態,事務不會查看到中間狀態的數據。

  4. 持久性(Durability)
    指的是隻要事務成功結束,它對數據庫所做的更新就必須永久保存下來。即使發生系統崩潰,重新啓動數據庫系統後,數據庫還能恢復到事務成功結束時的狀態。

下面我們再說事務的隔離級別

  1. 事務隔離是事務在數據庫讀寫方面的控制範圍。在讀取數據庫的過程中,如果兩個事務併發執行,那麼彼此之間的數據是如何影響。

  2. 說隔離級別前我們先說幾個名稱

    1. 髒讀
      髒讀是表示兩個事務之間,一個事務在修改數據過程中,還沒提交事務,但是另外一個事務讀取了他修改的數據然後用來進行相關操作,而後來在修改的那個事務沒執行成功進行了回滾,就是這個數據恢復了事務執行前的數據,並沒有進行修改,而那個讀取了事務中的數據進行相關操作的就是錯誤的數據了,這時候就發生了髒讀。

    2. 不可重複讀
      不可重複度表示兩個事務之間,一個事務在讀取這個數據然後進行相關操作,這時候另外一個數據對這個數據進行了修改提交了,然後那個事務再來讀這個數據的時候,發現這個數據怎麼和我開始讀的時候不一樣了,這是時候就發生了不可重複讀。

    3. 幻讀
      幻讀表示兩個事務之間,一個事務對這個表進行了讀取這個條件發現了有10條數據,然後另外一個事務對這個表進行了插入2條數據,也符合一開始那個事務的條件的數據,此時一開始那個事務再讀這個條件的時候,怎麼變成了12條,這時候就發生了幻讀。

    4. 區別不可重複度和幻讀:
      不可重複度重修改,幻讀重數據數量的變化(刪除修改)

  3. 數據庫的4個隔離級別

    1. Read Uncommited-讀未提交
      這個是隔離級別最低的一個,他允許另外一個事務讀取沒提交的數據,可能導致髒讀,不可重複度,幻讀

    2. Read Committed-讀提交
      這個隔離級別保證一個事務修改的數據提交後才能被另外一個事務讀取,可以防止髒讀,但是可能導致不可重複度和幻讀

    3. Repeatable Read-可重複讀
      這個隔離級別保證一個事務相同條件下前後兩次獲取的數據是一致的,可以防止髒讀和不可重複度,但是可能導致幻讀

    4. Serializable-串行
      這個級別保證事務一個一個執行,可以防止髒讀、不可重複度和幻讀。但是這將嚴重影響程序的性能。通常情況下也不會用到該級別。

  4. Spring的隔離級別

    • Spring隔離級別多了一個default,就是使用數據庫默認的隔離級別
    • 注:sql server,Oracle默認使用的是Read Committed, MySQL默認使用的是Repeatable Read
  5. 在方法上使用註解的方式設置隔離級別

    • import org.springframework.transaction.annotation.Transactional;
      import org.springframework.transaction.annotation.Isolation;
      
      @Transactional(isolation = Isolation.DEFAULT)
      

我們繼續說Spring事務的傳播行爲

  1. 什麼是事務的傳播

    • 就是當我們在Service中調用別的Service的時候,兩個Service的事務該怎麼傳遞
    • 也就是爲了解決Service方法之間互相調用的事務問題
  2. 當事務方法被另一個事務方法調用時,必須指定事務應該如何傳播。

  3. Spring在TransactionDefinition定義中包括瞭如下幾個表示傳播行爲的常量:

    1. int PROPAGATION_REQUIRED = 0;
      int PROPAGATION_SUPPORTS = 1;
      int PROPAGATION_MANDATORY = 2;
      int PROPAGATION_REQUIRES_NEW = 3;
      int PROPAGATION_NOT_SUPPORTED = 4;
      int PROPAGATION_NEVER = 5;
      int PROPAGATION_NESTED = 6;
      
  4. 其中0、1、2爲支持當前事務,3、4、5,爲不支持當前事務,6是一個特殊的。

  5. 再說下這7中傳播行爲

    1. **PROPAGATION_REQUIRED:**如果當前存在事務,則加入該事務;如果當前沒有事務,則創建一個新的事務。
    2. **PROPAGATION_SUPPORTS:**如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式執行。
    3. **PROPAGATION_MANDATORY:**如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。
    4. **PROPAGATION_REQUIRES_NEW:**創建一個新的事務,如果當前存在事務,則把當前事務掛起,等新事務執行完成後再執行掛起的事務。
    5. **PROPAGATION_NOT_SUPPORTED:**以非事務的方式執行,如果當前存在事務,則把當前事務掛起,等新事務執行完成後再執行掛起的事務。
    6. **PROPAGATION_NEVER:**以非事務的方式執行,如果當前存在事務,則拋出異常。
    7. PROPAGATION_NESTED:如果當前存在事務,則創建一個事務作爲當前事務的嵌套事務來運行;以PROPAGATION_NESTED啓動的事務如果存在外部事務的話就內嵌於外部事務中,這個時候內嵌事務並不是一個獨立的事務,它依賴於外部事務,只有通過外部的事務提交,自己的事務纔會提交;外部事務如果回滾,嵌套的子事務也會回滾。嵌套的子事務不能單獨提交。如果不存在外部事務的話就按PROPAGATION_REQUIRED的規則來。

以上便是我對Spring事務的四個特性,以及Spring的隔離級別和傳播機制的一些總結,如有不對之處,請幫我指出以便我及時更正。

終於把Spring事務的相關知識也進行了梳理,之前一直對此不怎麼了解,在最近工作的時候發現了這塊出現了問題,然後再進行各種查詢,解決了問題,決定整理一篇博客進行記錄。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章