偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

告別Spring事務(wù)Bug!詳解傳播行為與隔離級別的組合陷阱與最佳實踐

開發(fā) 前端
Spring 事務(wù)的傳播特性和隔離級別提供了靈活且強大的并發(fā)控制手段。它們可以自由組合使用,沒有預(yù)定義的固定組合列表。

在 Spring 事務(wù)管理中,傳播行為 (Propagation Behavior) 和 隔離級別 (Isolation Level) 是兩個獨立但可以組合使用的核心概念。它們分別解決了不同維度的事務(wù)控制問題:

  1. 傳播行為 (Propagation Behavior): 定義了一個事務(wù)方法被另一個事務(wù)方法調(diào)用時,事務(wù)應(yīng)該如何傳播。它解決了事務(wù)的作用域和邊界問題(例如,是加入現(xiàn)有事務(wù),還是開啟一個新事務(wù),還是非事務(wù)執(zhí)行)。
  2. 隔離級別 (Isolation Level): 定義了多個并發(fā)事務(wù)同時訪問和修改相同數(shù)據(jù)時,一個事務(wù)能看到其他事務(wù)未提交或已提交數(shù)據(jù)的程度。它解決了事務(wù)之間的可見性問題,旨在防止臟讀、不可重復(fù)讀、幻讀等并發(fā)問題。

組合方式

關(guān)鍵點:傳播行為和隔離級別是正交的,理論上可以任意組合使用。 沒有固定的“官方組合列表”,因為選擇哪種組合完全取決于你的具體業(yè)務(wù)場景和并發(fā)控制需求。

傳播行為 (7種)

  1. REQUIRED (默認): 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則創(chuàng)建一個新事務(wù)。
  2. SUPPORTS: 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則以非事務(wù)方式執(zhí)行。
  3. MANDATORY: 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則拋出異常。
  4. REQUIRES_NEW: 創(chuàng)建一個新事務(wù),并掛起當(dāng)前事務(wù)(如果存在)。新事務(wù)獨立提交或回滾,不受外部事務(wù)影響。
  5. NOT_SUPPORTED: 以非事務(wù)方式執(zhí)行操作,并掛起當(dāng)前事務(wù)(如果存在)。
  6. NEVER: 以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù),則拋出異常。
  7. NESTED: 如果當(dāng)前存在事務(wù),則在當(dāng)前事務(wù)內(nèi)創(chuàng)建一個嵌套事務(wù)(保存點)。嵌套事務(wù)可以獨立于外部事務(wù)進行回滾。如果當(dāng)前沒有事務(wù),其行為與 REQUIRED 相同。

隔離級別 (5種)

  1. DEFAULT (默認): 使用底層數(shù)據(jù)庫的默認隔離級別。對于大多數(shù)數(shù)據(jù)庫(如 MySQL, PostgreSQL),通常是 READ_COMMITTED。
  2. READ_UNCOMMITTED: 最低的隔離級別。允許讀取其他事務(wù)尚未提交的更改(臟讀)??赡軐?dǎo)致臟讀、不可重復(fù)讀和幻讀。
  3. READ_COMMITTED: 保證一個事務(wù)只能讀取到其他事務(wù)已提交的數(shù)據(jù)??煞乐古K讀,但可能出現(xiàn)不可重復(fù)讀和幻讀。這是許多數(shù)據(jù)庫的默認級別。
  4. REPEATABLE_READ: 保證在同一個事務(wù)中多次讀取同一數(shù)據(jù)的結(jié)果是一致的(即使其他事務(wù)修改并提交了該數(shù)據(jù))。可防止臟讀和不可重復(fù)讀,但可能出現(xiàn)幻讀(MySQL InnoDB 通過 MVCC 機制在這個級別也避免了幻讀)。
  5. SERIALIZABLE: 最高的隔離級別。所有事務(wù)按順序依次執(zhí)行。完全防止臟讀、不可重復(fù)讀和幻讀,但性能開銷最大,并發(fā)性最低。

如何組合與選擇?

你可以為任何使用了 @Transactional 注解的方法(或類)同時指定propagation 和 isolation 屬性。

@Service
publicclass MyService {

    @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.REPEATABLE_READ)
    public void performCriticalUpdate() {
        // 這個方法總是在一個新的事務(wù)中執(zhí)行,該事務(wù)的隔離級別是 REPEATABLE_READ
        // 外部事務(wù)(如果存在)會被掛起
        // ...
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED) // 顯式聲明默認值
    public void standardOperation() {
        // 這個方法加入現(xiàn)有事務(wù)或創(chuàng)建新事務(wù)(REQUIRED),使用 READ_COMMITTED 隔離級別
        // ...
    }

    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void nonTransactionalOperation() {
        // 這個方法以非事務(wù)方式執(zhí)行,不關(guān)心隔離級別(因為沒事務(wù))
        // ...
    }
}

組合時的注意事項

  1. 傳播行為主導(dǎo)事務(wù)邊界: 傳播行為決定了方法執(zhí)行時是否有事務(wù)、是新事務(wù)還是加入現(xiàn)有事務(wù)。隔離級別只在事務(wù)存在時才生效。對于 NOT_SUPPORTEDNEVERSUPPORTS(當(dāng)沒有當(dāng)前事務(wù)時) 這些傳播行為,方法內(nèi)的操作是在非事務(wù)上下文中執(zhí)行的,指定的隔離級別將被忽略。
  2. 新事務(wù)與隔離級別: 當(dāng)傳播行為導(dǎo)致創(chuàng)建新事務(wù)時(如 REQUIRED 在無事務(wù)時、REQUIRES_NEWNESTED),新事務(wù)會使用該方法指定的隔離級別(如果未指定,則使用默認值,通常是 DEFAULT -> 數(shù)據(jù)庫默認)。
  3. 加入現(xiàn)有事務(wù)與隔離級別: 當(dāng)傳播行為導(dǎo)致加入現(xiàn)有事務(wù)時(如 REQUIREDSUPPORTSMANDATORY 在有事務(wù)時),該方法指定的隔離級別通常會被忽略。它會沿用現(xiàn)有事務(wù)的隔離級別。這是為了保持整個事務(wù)的一致性。你不能在一個已經(jīng)運行的事務(wù)中途改變其隔離級別。
  4. 嵌套事務(wù) (NESTED):NESTED 在現(xiàn)有事務(wù)內(nèi)創(chuàng)建的是一個保存點。雖然它有自己的“回滾點”,但它仍然運行在外部事務(wù)的隔離級別下。你不能為嵌套事務(wù)指定一個不同于外部事務(wù)的隔離級別。隔離級別作用于整個外部事務(wù)。
  5. 性能與正確性的權(quán)衡: 隔離級別越高(如 SERIALIZABLE),并發(fā)控制越嚴格,數(shù)據(jù)一致性越好,但性能開銷(鎖競爭、回滾段管理)也越大。傳播行為如 REQUIRES_NEW 能提供獨立的事務(wù)邊界,但頻繁創(chuàng)建新事務(wù)也有開銷。選擇組合時需要根據(jù)業(yè)務(wù)邏輯對數(shù)據(jù)一致性的要求和對性能的敏感度進行平衡。
  6. 數(shù)據(jù)庫支持: 并非所有數(shù)據(jù)庫都支持所有的隔離級別或傳播行為(尤其是 NESTED)。例如,Oracle 不支持 REPEATABLE_READ,JDBC 規(guī)范也不要求支持 NESTED。在使用前需確認你的數(shù)據(jù)庫和 JDBC 驅(qū)動支持所選的組合。

常見的組合場景示例

  1. REQUIRED + READ_COMMITTED (最常見默認組合): 適用于大多數(shù)業(yè)務(wù)邏輯,平衡了數(shù)據(jù)一致性和性能。
  2. REQUIRES_NEW + READ_COMMITTED/REPEATABLE_READ:
  • 場景: 記錄審計日志、發(fā)送通知消息。即使主業(yè)務(wù)邏輯失敗回滾,這些輔助操作也需要成功提交。
  • 說明: 使用 REQUIRES_NEW 確保日志/消息獨立提交。隔離級別根據(jù)日志讀取需求選擇,通常 READ_COMMITTED 足夠。
  1. REQUIRED + REPEATABLE_READ/SERIALIZABLE:
  • 場景: 對數(shù)據(jù)一致性要求極高的核心操作,如金融交易、庫存扣減(防止超賣)。
  • 說明: 提高隔離級別防止不可重復(fù)讀或幻讀對業(yè)務(wù)邏輯造成的干擾。
  1. SUPPORTS + DEFAULT:
  • 場景: 查詢方法。如果有事務(wù)(例如在寫操作中調(diào)用查詢),則加入事務(wù)保證查詢到最新提交的數(shù)據(jù)(READ_COMMITTED);如果沒有事務(wù),則直接執(zhí)行簡單查詢。
  1. NOT_SUPPORTED + (忽略):
  • 場景: 執(zhí)行一些與事務(wù)無關(guān)、或必須繞過事務(wù)的耗時操作(如文件 I/O、調(diào)用外部非事務(wù) API)。
  • 說明: 掛起當(dāng)前事務(wù)(如果存在),避免長事務(wù)持有鎖,提高并發(fā)性。隔離級別無意義。
  1. NESTED + REPEATABLE_READ (理想配合):
  • 場景: 一個復(fù)雜操作中的子操作,該子操作可能失敗但不希望導(dǎo)致整個大操作回滾(只需回滾到子操作前的保存點)。
  • 說明:REPEATABLE_READ 或 SERIALIZABLE 能更好地保證在嵌套事務(wù)回滾點之后,外部事務(wù)再次讀取數(shù)據(jù)時的一致性(避免讀到嵌套事務(wù)內(nèi)已回滾的中間狀態(tài))。但需注意數(shù)據(jù)庫支持情況(如 MySQL InnoDB 支持 NESTED)。

總結(jié)

Spring 事務(wù)的傳播特性和隔離級別提供了靈活且強大的并發(fā)控制手段。它們可以自由組合使用,沒有預(yù)定義的固定組合列表。選擇哪種組合取決于:

  • 業(yè)務(wù)邏輯的事務(wù)邊界需求 (傳播行為): 操作是否需要事務(wù)?需要新事務(wù)還是加入現(xiàn)有事務(wù)?
  • 業(yè)務(wù)邏輯的數(shù)據(jù)一致性需求 (隔離級別): 操作對臟讀、不可重復(fù)讀、幻讀的容忍度如何?
  • 性能考量: 更高的隔離級別和創(chuàng)建新事務(wù) (REQUIRES_NEW) 通常帶來更大的開銷。
  • 數(shù)據(jù)庫支持: 確認選用的組合在你的數(shù)據(jù)庫和 JDBC 驅(qū)動上有效。

理解每個傳播行為和隔離級別的含義及其組合時的相互作用(特別是關(guān)于新事務(wù)創(chuàng)建和加入現(xiàn)有事務(wù)時隔離級別的處理規(guī)則),是正確配置 Spring 事務(wù)的關(guān)鍵。務(wù)必根據(jù)具體業(yè)務(wù)場景仔細權(quán)衡選擇。

責(zé)任編輯:武曉燕 來源: Java技術(shù)指北
相關(guān)推薦

2021-09-02 18:39:01

Spring隔離級別

2021-12-27 09:20:13

事務(wù)模式隔離

2010-11-19 16:13:06

oracle事務(wù)隔離級

2009-06-29 17:54:47

Spring事務(wù)隔離

2022-06-10 11:51:49

MySQL事務(wù)隔離

2024-12-02 08:37:04

2025-01-13 13:12:54

2020-10-13 10:32:24

MySQL事務(wù)MVCC

2022-08-27 14:14:06

Spring事務(wù)開發(fā)

2020-03-05 09:33:15

數(shù)據(jù)庫事務(wù)隔離事務(wù)

2022-09-19 06:16:23

事務(wù)隔離級別Spring

2022-05-20 10:20:17

Spring事務(wù)MyBatis

2022-10-09 20:52:19

事務(wù)隔離級別傳播機制

2018-12-19 16:46:38

MySQL事務(wù)隔離數(shù)據(jù)庫

2025-05-12 01:33:00

異步函數(shù)Promise

2021-07-26 10:28:13

MySQL事務(wù)隔離

2024-04-26 09:17:20

MySQL事務(wù)隔離

2021-08-04 13:19:42

MySQL 事務(wù)隔離

2010-09-07 08:47:54

B2隔離級別

2024-03-08 10:50:44

Spring技術(shù)應(yīng)用程序
點贊
收藏

51CTO技術(shù)棧公眾號