「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > @Transactional のデフォルトの分離パラメータと伝播パラメータを調整する必要があるのはいつ、なぜですか?

@Transactional のデフォルトの分離パラメータと伝播パラメータを調整する必要があるのはいつ、なぜですか?

2024 年 11 月 6 日に公開
ブラウズ:817

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

@Transactional の分離パラメータと伝播パラメータ

Spring の @Transactional アノテーションでは、分離と伝播という 2 つの重要なパラメータがデータベース トランザクションの動作を定義します。 。この記事では、デフォルト値の調整を検討する必要がある場合とその理由について説明します。

伝播

伝播は、トランザクションが相互にどのように関連するかを定義します。一般的なオプションは次のとおりです。

  • REQUIRED: 既存のトランザクション内でコードを実行するか、存在しない場合は新しいトランザクションを作成します。
  • REQUIRES_NEW: 常に新しいトランザクションを作成し、既存のトランザクションを一時停止します。

デフォルト値: 必須

分離

分離は、トランザクション間のデータ コントラクトを定義します。他のトランザクションによるデータ変更の可視性レベルを指定することで、特定のデータの不整合を防ぎます。主要な分離レベルは次のとおりです:

  • READ_UNCOMMITTED: ダーティ リードに対する保護なし。
  • SERIALIZABLE: 最も強力な分離で、データの競合がないことを保証します。

デフォルト値: データベースによって異なります (例: MariaDB の REPEATABLE_READ)

実際の例

ダーティ読み取りの問題を考えてみましょう。トランザクションは、別のトランザクションによって行われたコミットされていない変更を読み取ることができます。

                                       Thread 1          Thread 2
                                               |              |
                                             Write(x)           |
                                               |              |
                                               |             Read(x)
                                               |              |
                                             Rollback           |
                                                 |             |
                                                   Value (x) is now dirty (incorrect)

このシナリオでは、ダーティ読み取りを防ぐために、分離レベルを READ_COMMITTED に設定し、伝播レベルを REQUIRED に設定できます。 ]。この組み合わせにより、トランザクションは他のトランザクションによってコミットされたデータのみを読み取るようになります。

トランザクションのカスタマイズ

次の例では、provideService メソッド常に新しいトランザクション内で実行され、他の同時タスクによる変更がその実行に干渉しないようにします:

@Transactional(propagation=Propagation.REQUIRES_NEW)
public void provideService() {
    repo1.retrieveFoo();
    repo2.retrieveFoo();
}

トランザクション動作のテスト

さまざまな伝播レベルの動作を検証するには、Java テストを使用できます:

@Test
public void testProvideService() {
    TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
    fooService.provideService();
    transactionManager.rollback(status);
    // Assert repository values are unchanged ...
}

REQUIRES_NEW を使用すると、fooService.provideService() は別のトランザクション内で動作するため、ロールバックされません。 REQUIRED を指定すると、すべてがロールバックされます。

最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3