1

tomcat 7 と MySQL 5.5 で実行される大規模なエンタープライズ アプリケーションに、JPA 2 と Spring 3.0.5 で Hibernate 3.6.0.Final を使用しています。アプリケーション内のトランザクションのほとんどは 1 秒未満で存続し、5 ~ 10 個のエンティティを更新しますが、ユース ケースによっては、1 回のトランザクションで 10 ~ 20,000 個を超えるエンティティを更新する必要があります。これには数分かかるため、70% 以上の時間がかかります。これらのエンティティの一部が他のトランザクションによって更新されたため、このようなトランザクションは StaleObjectStateException で失敗します。

通常、すべてのテーブルでバージョン列を維持し、StaleObjectStateException の場合は通常再試行しますが、これらの長いトランザクションはとにかく非常に長いため、再試行を続けると、StaleObjectStateException をエスケープできるかどうかもわかりません。

また、多くのアクティビティが忙しい時間帯にこれらのエンティティを更新し続けるため、システム内の多くのアクティビティが停止する可能性があるため、悲観的なアプローチをとることはできません。

いくつかの失敗したトランザクションといくつかの成功したトランザクションの場合に混乱したデータを許容できないため、何千もの独立した小さなトランザクションを生成できないため、このような長いトランザクションの問題を修正する方法を提案してください。

4

1 に答える 1

1

1回のトランザクションで20,000のエンティティを変更することは、通常よりもはるかに多くのことです。

私はあなたに一般的な解決策を与えることはできませんが、ここに問題を解決する方法のいくつかのアイデアがあります。

1)LockMode.UPGRADEを使用します(悲観的ロックを参照)。そこで、「SELECT FOR UPDATE」を明示的に生成します。これにより、他のユーザーがロックされている間、行を変更できなくなります。これで問題を回避できますが、大規模なトランザクションが多すぎると、デッドロック(プログラミングによって異なります)またはタイムアウトが発生する可能性があります。

2)これらの大規模なトランザクションを回避するために、データモデルを変更します。なぜ10,000行を更新する必要があるのですか?おそらく、非常に多くの行で更新されるこの情報を新しいテーブルに入れて、それを参照するだけにすることができるので、新しいテーブルの数行だけを更新する必要があります。

3)Sessionの代わりにStatelessSessionを使用します。この場合、例外の後にロールバックを強制されることはありません。代わりに、問題を修正して続行できます(この場合、その間に変更されたエンティティをリロードし、リロードされたエンティティで大規模なトランザクションの変更を行います)。これにより、大規模なトランザクション全体ではなく、重要なイベント(その間に行が変更された)を行ごとに処理できる可能性があります。

于 2012-07-05T12:18:46.460 に答える