web-dev-qa-db-ja.com

Spring transaction REQUIRED vs REQUIRES_NEW:ロールバックトランザクション

propagation = Propagation.REQUIRES_NEWトランザクションプロパティを持つメソッドがあります。

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void createUser(final UserBean userBean) {
    //Some logic here that requires modification in DB
}

このメソッドは、複数回同時に呼び出すことができ、エラーが発生した場合は、トランザクションごとに(他のトランザクションとは独立して)ロールバックできます。

問題は、これにより、別のトランザクションが使用可能であっても、Springが複数のトランザクションを作成し、パフォーマンスの問題を引き起こす可能性があることです。


propagation = Propagation.REQUIREDのJavaドキュメントは言う:Support a current transaction, create a new one if none exists.

これにより、パフォーマンスの問題が解決されるようです。

ロールバックの問題はどうですか?既存のトランザクションの使用中に新しいメソッド呼び出しがロールバックした場合はどうなりますか?それは以前の呼び出しでもトランザクション全体をロールバックしませんか?

[編集]私の質問は十分に明確ではなかったと思います。

サーバーには数百のクライアントが接続されています。

クライアントごとに、当然トランザクションに関するフィードバックを送信する必要があります(OKまたは例外->ロールバック)。

私の質問は、REQUIREDを使用する場合、1つのトランザクションのみが使用されることを意味し、100番目のクライアントで問題が発生した場合、1番目のクライアントのトランザクションもロールバックしますか?

46
Majid Laissi

REQUIRES_NEWの使用は、メソッドがトランザクションコンテキストから呼び出される場合にのみ関連します。メソッドが非トランザクションコンテキストから呼び出されると、REQUIREDとまったく同じように動作します-新しいトランザクションを作成します。

これは、すべてのクライアントに対して1つのトランザクションのみが存在することを意味するものではありません。各クライアントは非トランザクションコンテキストから開始し、リクエスト処理が@Transactionalにヒットするとすぐに、新しいクライアントを作成しますトランザクション。

したがって、そのことを念頭に置いて、REQUIRES_NEWを使用すると、その操作のセマンティクスに意味がある場合-パフォーマンスを心配しないよりも-これは教科書の時期尚早な最適化になります-私はむしろ正確さとデータの整合性を重視し、パフォーマンスを心配しますパフォーマンスメトリックが収集されると、以前ではありません。

ロールバック時-REQUIRES_NEWを使用すると、新しいトランザクションが強制的に開始されるため、例外はそのトランザクションをロールバックします。同様に実行されていた別のトランザクションもある場合-例外がスタックをバブルするかキャッチされるかに応じてロールバックされるかしないか-操作の詳細に基づいて選択します。また、トランザクション戦略とロールバックに関するより詳細な議論については、 "トランザクション戦略:トランザクションの落とし穴を理解する"、Mark Richards をお勧めします。

69
Eugen

本当に別のトランザクションで実行する必要がある場合は、REQUIRES_NEWを使用し、パフォーマンスのオーバーヘッドに耐える必要があります。デッドロックに注意してください。

私はむしろ他の方法でそれをしたい:

  • Java side。
  • すべてのトランザクションを1つのトランザクションで実行します。
  • DB側で問題が発生した場合-> DBまたは検証設計の重大なエラーです。すべてをロールバックし、重大なトップレベルエラーをスローします。
  • 適切な単体テストを作成します。
11
Piotr Gwiazda