7

上下文是:

  • 生产者(JTA 事务PT)正在向 JMS 队列发送消息并进行数据库更新;
  • 消费者(JTA 事务CT)在同一队列上侦听并在收到消息时读取 DB;
  • 应用程序服务器 - WebLogic,DB - Oracle。

我观察到,有时CT(还没有?)能够看到PT的 DB 更改,如果已经收到相应的 JMS 消息(PT已提交?)。

似乎 JTA 不能保证这种一致性(这在 Jurgen Holler 的演示文稿“Transaction Choices for Performance”中也得到了证实)。

避免此类问题的最佳方法是什么(除了明显的 - 不使用 JTA)?

谢谢。

4

3 回答 3

4

因此,似乎没有简单、优雅和防故障的解决方案。在我们的案例中,决定依赖简单的重新传递机制(抛出异常并让 JMS 消息在一定时间后重新传递)。

还考虑了:

  • 将 DB 数据源标记为并期望启动最后资源提交优化 (LRCO)(从而部分控制 XA 事务中的提交顺序)。由于依赖于应用程序服务器 (WL) 的内部而被拒绝。

  • 将 DeliveryDelay 设置为 JMS 消息,因此只有在(假设)数据库同步结束时,它才能在一段时间后使用。由于缺乏保证而被拒绝,需要针对不同的环境进行微调。

其他答案中提到的博客文章确实包含所有这些以及涵盖的其他几个选项(但没有确定的选项)。

于 2013-02-07T17:42:34.253 回答
1

此处概述了一些选项:http: //jbossts.blogspot.co.uk/2011/04/messagingdatabase-race-conditions.html

于 2013-01-30T12:14:17.267 回答
0

关于答案:

“因此,似乎没有简单、优雅和防故障的解决方案。在我们的案例中,决定依赖简单的重新传递机制(抛出异常并让 JMS 消息在一定时间后重新传递)。”

仅当您在 Transaction1 逻辑结束后开始的第二个事务有一种方法可以检测到 Transaction 1 更改尚不可见并在技术异常时自行爆炸时,这才是失败证明。

当您的事务 2 与事务 1 的进程不同时,这很可能可以检查。很可能事务 1 的输出对于事务 2 的成功是必要的。如果你有土豆,你只能做薯条......如果你没有土豆,你可以炸毁下次再试一次。

但是,如果您的进程因数据库过时而中断,则该进程与在事务 1 本身上运行的进程完全相同。您只是将土豆添加到肠道(例如 db 表)中,并且未能检测到您的肠道溢出并继续运行事务以提高...这样的检查可能不在您的手中。

类似的事情,恰好是我的情况。

对此的理论解决方案很可能是尝试通过创建与 JPA 的 @Version 字段等效的人工实体来在 DB 上引发脏读,从而强制需要串行运行的每个进程对公共实体进行更新。如果事务 2 和事务 1 都更新了公共实体上的公共字段,则该过程将不得不中断——要么您在第二个事务上收到 JPA 乐观锁异常,要么您从数据库中收到脏读更新异常。

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

于 2016-06-29T13:45:03.810 回答