」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 何時以及為何應調整 @Transactional 中的預設隔離和傳播參數?

何時以及為何應調整 @Transactional 中的預設隔離和傳播參數?

發佈於2024-11-06
瀏覽:341

When and Why Should You Adjust the Default Isolation and Propagation Parameters in @Transactional?

@Transactional中的隔離和傳播參數

在Spring的@Transactional註解中,兩個關鍵參數定義了資料庫事務的行為:隔離和傳播。本文探討了何時以及為何應考慮調整其預設值。

傳播

傳播定義了事務如何相互關聯。常見選項包括:

  • REQUIRED: 在現有交易中執行程式碼,如果不存在則建立一個新交易。
  • REQUIRES_NEW: 始終建立新事務,暫停任何現有事務。

預設值: 必需

預設值: 必需

隔離
  • 隔離性定義了事務之間的資料契約。它透過指定其他事務所所做的資料更改的可見性等級來防止某些資料不一致。主要隔離等級為:
  • READ_UNCOMMITTED: 不保護髒讀。

SERIALIZABLE: 最強隔離,確保無資料衝突。

預設值: 因資料庫而異(例如,MariaDB 的REPEATABLE_READ)

實際範例
                                       Thread 1          Thread 2
                                               |              |
                                             Write(x)           |
                                               |              |
                                               |             Read(x)
                                               |              |
                                             Rollback           |
                                                 |             |
                                                   Value (x) is now dirty (incorrect)

考慮髒讀問題,其中一個事務可以讀取另一個事務所所做的未提交的變更。 線程 1 線程 2 | | 寫(x) | | | | 讀(x) | | 回滾 | | | 值(x) 現在是髒的(不正確)在這種情況下,為了防止髒讀,您可以將隔離等級設為

READ_COMMITTED

並將傳播等級設為REQUIRED。這種組合確保事務只讀取其他事務已提交的資料。

自訂事務

@Transactional(propagation=Propagation.REQUIRES_NEW)
public void provideService() {
    repo1.retrieveFoo();
    repo2.retrieveFoo();
}
方法始終在新事務中運行,確保其他並發任務所做的任何更改不會幹擾其執行:

@Transactional(propagation=Propagation.REQUIRES_NEW) 公共無效提供服務(){ repo1.retrieveFoo(); repo2.retrieveFoo(); }

測試事務行為
@Test
public void testProvideService() {
    TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
    fooService.provideService();
    transactionManager.rollback(status);
    // Assert repository values are unchanged ...
}
要驗證不同傳播層級的行為,可以使用 Java 測試:

@Test 公共無效testProvideService(){ TransactionStatus 狀態 = transactionManager.getTransaction(new DefaultTransactionDefinition()); fooService.provideService(); transactionManager.rollback(狀態); // 斷言儲存庫值未更改... }使用 REQUIRES_NEW

fooService.provideService()

不會回滾,因為它在單獨的事務中操作。使用When and Why Should You Adjust the Default Isolation and Propagation Parameters in @Transactional? 
REQUIRED

,一切都會回滾。

最新教學 更多>

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3