环境:
我们有一个应用程序部署在 JBoss 4.2.3.GA 服务器中,它使用Hibernate 3.4 和 JTA 1.0。
有一个导入器创建或更新某些实体,然后导入一些数据。由于多种原因,大部分导入是在新事务中完成的,在每个事务中,在外部事务中创建/更新的实体可能会再次更新。
调用序列类似于以下伪代码:
服务1:
//container managed transaction T1 is started here
import() {
A a = ... ;//new or read from database
if( isNew( a ) ) {
create(a);
} else {
update(a);
}
Service1 s = ...; //injected or looked up
for( D d : someDataList ) {
//nested transaction T2 is started due to this call, T1 should be suspended
s1.importData(d);
//nested transaction T2 should have been committed here
}
服务2:
@TransactionAttribute(REQUIRES_NEW)
importData(D d) {
A a = ...; //get the corresponding A instance and update as needed
update(a);
//other stuff such as importing d
}
问题:
现在的问题是,我们最终会遇到一个竞争条件,有几个事务试图锁定相同的表,但到目前为止,我们既无法重现问题,也无法确定真正的原因。
不过,我们有一些假设:
由于在 T1 期间更新了某些实体,因此转换会获取一些数据库锁。然后,T1 被挂起,因为 T2 已启动,而 T2 又会尝试获取相同的数据库锁,因此被阻止。T2 最终会超时,然后 T1 可以正常完成并释放锁。
可能的解决方案?:
到目前为止,似乎只有一个可能的解决方案:将T1中的所有更新打包到另一个事务T1*中(可能完全跳过T1),并让T1*和T2按顺序运行。
如果业务案例允许这样做,这是否是一个合理的解决方案(我不确定,因为我自己没有实现该业务案例)?
可能还有其他解决方案,如果有,请提供一些提示。然而,我对此表示怀疑,因为似乎T1必须在T2尝试获取锁之前释放锁,因此基本上使T1和T2按顺序运行。
问题
从上面可以看出以下问题:
感谢您阅读本文:)
更新1:
因为我不是代码的作者,所以我也必须深入研究它。到目前为止,Hibernate中没有任何显式锁定的提示,因此AFAIK Hibernate只在写入数据库时使用数据库锁。当数据库连接打开时。
我们使用的是自动刷新,因此在某些情况下,T1 可能会在 T2 尝试相同的连接之前打开连接,但 T1 无法提交并关闭连接,因为它在 T2 提交之前处于挂起状态。因此,数据库似乎由于 T1 的刷新而获得的锁也无法在 T2 刷新之前释放。
使用手动刷新不是一个解决方案,因为如果T2在T1之前提交,我们就会丢失更新,但对实体的更改则相反。我知道这是设计中的一个缺陷,我们需要修复它,但我也想确认我们的假设是正确的,以便提供合理的修复:)
我会尽力提供一些线索,
你说桌子被锁了。我不知道你在哪里做这件事。默认情况下,Hibernate不会获取任何锁。您需要明确告诉它这样做,请参见。即使在这里,您也不是在表上获得锁,而是在单行上获得锁。只有当您使用悲观锁定并且两个事务都需要在同一行上锁定时,您的假设才能成立。
如果您没有使用悲观锁定,那么在T1尝试提交时应该会出现乐观锁定异常。所以,您的场景可能会导致同一个对象不被两个事务更新。
如果不进行调试,并且不知道“创建”和“更新”中发生了什么,就很难回答您的问题。
问题内容: JTA为什么不支持嵌套事务?是因为实现它们的复杂性(我对此表示怀疑)还是某些设计原则? 问题答案: (正如@Piotr Nowicki指出的那样,JTA 确实 允许嵌套事务,但这不是强制性的可选操作。) 为什么?这是无法确定地回答的问题之一,除非您是做出决定时“在房间里”的人之一。 将嵌套事务作为规范的一部分包括在内可能是固有的复杂性。或当时明显的复杂性;即他们不知道他们知道如何做一个
据我所知,当您尝试在提交前一个事务之前开始一个事务时,会发生这种异常。然而,我不明白为什么在我的情况下会有这种例外。 我有一个Web应用程序与以下servlet: 这是我的Compte对象: 这是我的DAO的接口: 这就是它的实施: 另外,这是我的Spring配置: 关联的应用程序。属性文件包含以下行: 最后,我有以下servlet过滤器,从这里开始事务: 这是在网络上映射的。如下所示的xml文件
问题内容: 我正在研究应用数据库架构更新的脚本。我已经使用start transaction / commit设置了所有的SQL更新脚本。我在命令行上将这些脚本传递给psql。 现在,我需要在一个事务中同时应用多个脚本。到目前为止,我想出的唯一解决方案是从原始脚本集中删除启动事务/提交,然后将它们卡在新的启动事务/提交块中。我正在编写perl脚本来即时执行此操作。 实际上,我想要嵌套事务,但是我无
我在tomcat服务器中使用具有多个数据源配置的JTA原子事务。有时我会遇到以下异常: JTA事务意外回滚(可能是由于超时);嵌套的异常是javax。交易回滚异常:事务被设置为仅回滚 出现这种异常的原因是什么?
并用@Transactional注释了具体类。 我们使用Jboss应用服务器支持通过JNDI与MQ集成。这里的问题是,如果监听器中的任何层有任何异常,则整个事务不会回滚,消息也不会移动到退出队列。很明显,当我们使用Hibernate事务管理器时,它不知道其他资源,如JMS事务。 我可以安全地用JTA事务替换它吗,因为Jboss将处理整个事务管理?这样做是否有任何可预见的风险?
我有一种情况,我必须提交一部分代码作为它自己的事务。 我已经创建了一个表: 以及plpython3u语言中的函数: 第一种情况: 表中的条目正确:1、2、4 第二种情况: 表中的值未填充 我希望或应该添加到表 中,但出乎意料的是没有插入任何值。我想象函数打开了一个新的子事务,它不应该依赖于父事务。如果我是对的,请告诉我。 Postgres中是否存在自主交易?或者我必须修改我的plpython3u函