トランザクションがコミットされる前にJMSメッセージの配信
-
19-09-2019 - |
質問
私はaを含む非常に簡単なシナリオを持っています データベース そしてa JMS アプリケーションサーバー(Glassfish)。シナリオはシンプルです:
1. an EJB inserts a row in the database and sends a message.
2. when the message is delivered with an MDB, the row is read and updated.
問題は、時々 挿入がコミットされる前にメッセージが配信されます データベース内。 2フェーズコミットプロトコルを考慮すると、これは実際に理解できます。
1. prepare JMS
2. prepare database
3. commit JMS
4. ( tiny little gap where message can be delivered before insert has been committed)
5. commit database
この問題について議論しました 他の人と, 、しかし、答えは常にでした: 「奇妙なことに、それは箱から出してうまくいくはずです」.
私の質問は次のとおりです。
- どうすれば箱の外で動作できますか?
- 私のシナリオはかなり簡単に聞こえますが、なぜ同様の問題を抱えている人がもっとないのですか?
- 私は何か間違ったことをしていますか?この問題を正しく解決する方法はありますか?
問題についての私の理解についてのもう少し詳細を次に示します。
このタイミングの問題は、参加者がこの順序で扱われた場合にのみ存在します。 2PCが参加者を逆注文(最初にデータベース、次にメッセージブローカー)で扱っている場合、それは問題ありません。問題はランダムに発生していましたが、完全に再現可能でした。
Glassfishドキュメントでは、JTA、JCA、およびJPA仕様の分散トランザクションの参加者の順序を制御する方法は見つかりませんでした。使用時に注文に応じて分散トランザクションに参加すると仮定できますが、JPAなどのORMを使用すると、データがフラッシュされ、データベース接続が実際に使用される時期を知ることは困難です。何か案が?
解決
You are experiencing the classic XA 2-PC race condition. It does happen in production environments.
There are 3 things coming to my mind.
- Last agent optimization where JDBC is the non-XA resource.(Lose recovery semantics)
- Have JMS Time-To-Deliver. (Deliberately Lose real time)
- Build retries into JDBC code. (Least effect on functionality)
Weblogic has this LLR optimization avoids this problem and gives you all XA guarantees.