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。

我还没有测试过这种方法,但很可能是需要的工作,遗憾的是。