【发布时间】:2011-01-25 23:21:37
【问题描述】:
我有一个非常简单的场景,涉及应用服务器 (Glassfish) 中的 数据库 和 JMS。场景非常简单:
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
我已经讨论过这个问题with others,但答案总是:“奇怪,它应该开箱即用”。
那么我的问题是:
- 如何开箱即用?
- 我的场景听起来很简单,为什么没有更多人遇到类似问题?
- 我做错了吗?有没有办法正确解决这个问题?
以下是关于我对问题的理解的更多细节:
仅当参与者按此顺序处理时,才会存在此时间问题。如果 2PC 以相反的顺序处理参与者(首先是数据库,然后是消息代理),那应该没问题。这个问题是随机发生的,但完全可以重现。
在 Glassfish 文档中,我发现无法控制 JTA、JCA 和 JPA 规范中分布式事务参与者的顺序。我们可以假设它们会在使用时按照顺序被登记到分布式事务中,但是使用 JPA 等 ORM 时,很难知道何时刷新数据以及何时真正使用数据库连接。有什么想法吗?
【问题讨论】:
-
问题:MDB 是否在同一台服务器上运行?如果是,MDB 是否也使用 JPA 来更新记录?如果是,您是否使用二级缓存(我在另一篇文章中读到您正在使用 Hibernate)?最后,如果是(使用缓存),我可以知道您使用的是什么缓存实现吗?
-
@Elister。一切都在同一台服务器上运行。我们到处使用 JPA。二级缓存完全被禁用。 (我们发现的解决方法是使用原生查询
select * for update来读取 MDB 中的行。然后它会等到第一个事务被提交。) -
你能显示一些伪代码吗?如果您使用不同的 EJB,等等
-
@Pascal 我创建了一个重现测试用例。这是源代码和说明:forums.java.net/jive/message.jspa?messageID=353154#391321
-
WebSphere 7 已添加此支持。查看“事务资源的提交优先级”部分publib.boulder.ibm.com/infocenter/wasinfo/fep/index.jsp?topic=/…
标签: database jakarta-ee jms distributed-transactions 2phase-commit