1

私が解決しようとしている問題について説明しようと思います。私が開発したアプリには、Spring トランザクション管理の実装が不十分であることに気付きました。サービス層メソッドではなく、DAO インターフェイス メソッド (CRUD) で定義されたトランザクションで宣言型アプローチを使用しています。これは、ある種のメッセージ処理を行う Web アプリであり、複数のスレッドが同じメッセージ インスタンスに対して同時に動作します。一般的な手順は次のとおりです。

  1. メッセージは T1 (トランザクション 1) で作成され、送信キューに入れられます。T1 は終了します。
  2. メッセージは別のスレッドによってキューから取得され、送信され、送信時刻といくつかの追加情報で更新されます。メッセージオブジェクトのプロパティを設定し、dao.update(m) を呼び出すと、t2 が起動します。
  3. t2 がコミットする前に、配信レポートが受信され、Tread3 は同じメッセージ オブジェクトを db (ステップ 1 で保存) で見つけて処理を開始し、その状態プロパティを更新して dao.upate(m) を呼び出し、t2 がまだ進行中に t3 が開始されるようにします。
  4. 別のスレッド (スレッド 4) は、t4 で状態を再度変更することにより、同じメッセージ オブジェクトをさらに処理します。

時々発生する結果は、t2 からの変更が失われ、送信時刻が db で null になることです。アプリの設計を改善し、同じメッセージの同時処理を防止することでこの問題を解消する方法を見つけるのに助けが必要です。

  1. トランザクションの再設計 (dao の代わりにサービス レベルで使用) と、シリアライズ可能な分離レベル (またはその他) の使用に集中する必要がありますか。

  2. JPAエンティティマネージャのロックを使用する必要がありますか?

アプリは、Spring 3 と JPA2 を休止状態の実装で使用します。

4

1 に答える 1

0

はい、トランザクションをサービス レベルに移動しますが、設計全体を再考し、プロセス全体を 1 つのスレッドにできるかどうかを確認します。私の記憶が正しければ、Spring のトランザクション管理はスレッドベースです。複数のスレッドにまたがるトランザクションを作成できるとは思えません。

また、可能であれば単純化して、データベースへのアクセスが 1 回だけになるようにします。本当に 4 つの個別の更新が必要な場合は、同じスレッドの同じトランザクションで順番に実行します。そうしないと、トランザクションをうまく機能させることができません。

明示的なロックはまた、傷の世界を求めています-それを行うと、デッドロックに陥る可能性が非常に高くなります.

編集:OPのコメントに応じて:

T3 更新を T2 更新から分離し、T3 更新を行う前に T2 トランザクションをコミットさせる方法を見つけることをお勧めします。

おそらく、配信レポートをメッセージ キューに入れます。次に、T3 でアイテムを見つけて、存在する場合は更新を実行し、存在しない場合は後で再試行するための戦略を立てます。

配信レポートの受信と T2 トランザクションの終了との間に最小または平均の時間があることがわかっている場合は、その遅延時間を配信受信の処理に組み込み、T3 更新を作成することができます。

于 2012-10-27T15:22:21.963 に答える