XA / JTA事务:在DB更改可见之前到达JMS消息
上下文是:
- producer(JTA transaction PT )既向JMS队列发送消息又进行DB更新;
- consumer(JTA事务CT )侦听同一队列并在收到消息时读取DB;
- 应用程序服务器 – WebLogic,DB – Oracle。
我观察到,如果已经收到相应的JMS消息( PT已经提交了?),有时CT不能(但是?)能够看到PT的 DB更改,事件。
似乎JTA不能保证这种一致性(这在Jurgen Holler的演讲“性能交易选择”中也得到了证实)。
避免此类问题的最佳方法是什么(除了明显的 – 不使用JTA)?
谢谢。
因此,似乎没有简单,优雅和防故障的解决方案。 在我们的例子中,决定依赖简单的重新传递机制(抛出exception并让JMS消息在一定时间后重新传递)。
还考虑:
-
将DB数据源标记为并期望上次资源提交优化(LRCO)启动(从而部分控制XA事务内的提交顺序)。 由于依赖于应用程序服务器(WL)的内部而被拒绝。
-
将DeliveryDelay设置为JMS消息,因此只有在(假设)数据库同步结束一段时间后才能使用它。 由于缺乏保证而被拒绝,需要针对不同的环境进行微调。
在其他答案中提到的博客文章确实包含所有这些以及其他几个选项(但没有确定的选项)。
这里概述了一些选项: http : //jbossts.blogspot.co.uk/2011/04/messagingdatabase-race-conditions.html
关于答案:
“因此,似乎没有简单,优雅和防故障的解决方案。在我们的案例中,决定依靠简单的重新传递机制(抛出exception并让JMS消息在一定时间后重新传递)。”
如果您在Transaction1逻辑结束后启动的第二个事务有一种方法可以检测到事务1更改尚未显示并且在技术exception上爆炸,则这只是失败certificate。
如果您的事务2与事务1的流程不同,则可能需要检查。 交易1的输出很可能是交易2成功的必要条件。 如果你有土豆,你只能制作炸薯条…如果你没有土豆,你可以炸掉,下次再试一次。
但是,如果由于数据库显示过时而导致进程中断的进程与在事务1本身上运行的进程完全相同。 您只是将土豆添加到肠道(例如数据库表)并且未能检测到您的肠道过度膨胀并继续运行交易以进行抽水……这样的检查可能无法完成。
有点像我的情况。
对此的理论解决方案很可能是通过创建一个等同于JPA的@Version字段的人工实体来尝试在DB上引发Dirty Read,迫使每个需要串行运行的进程来锤击对公共实体的更新。 如果事务2和1都更新公共实体上的公共字段,则该过程将不得不中断 – 您在第二个事务上获得JPA乐观锁定exception,或者如果从DB获得脏读取更新exception。
我还没有测试过这种方法,但很可能是需要的工作,遗憾的是。