使用TransactionAttributeType.NOT_SUPPORTED仍触发事务超时问题咨询
事务挂起后仍超时的问题解答
结论
这种行为完全符合JTA规范:事务被挂起时,超时计时不会暂停,依然会持续消耗直到事务结束或触发超时。
原因分析
JTA事务的超时是从事务创建时刻启动的全局计时机制,与事务是否被挂起无关。TransactionAttributeType.NOT_SUPPORTED的作用仅为让当前方法不参与事务,将原有事务临时挂起,但被挂起的事务生命周期并未中断——底层事务管理器(比如示例中的Arjuna)会持续监控超时时长,直到事务被提交/回滚,或者达到预设的超时阈值。
结合你的示例代码与日志来看:
Foo1.saveWith10secondsTimeout()启动了10秒超时的事务,执行完em.persist(entity)后调用Foo2.threadSleep15seconds()。Foo2的方法通过NOT_SUPPORTED挂起原事务,但原事务的10秒计时仍在正常运行。- 15:00:40(距事务启动刚好10秒)时,Arjuna的Transaction Reaper检测到超时,直接中止了原事务。
- 15秒后
Foo2的sleep执行完毕,回到Foo1时发现事务已被中止,最终触发回滚异常。
可行的解决办法
由于你无法重构代码或修改超时时间,推荐两种绕过思路:
- 异步执行耗时操作:给
Foo2.threadSleep15seconds()添加@Asynchronous注解,同时保留NOT_SUPPORTED。调用该方法会立即返回,原事务可在10秒内完成提交,耗时操作在后台线程独立执行,不会占用原事务的超时窗口。 - 调整事务执行顺序:如果业务逻辑允许,在
Foo1中先完成数据库操作并提交事务(需确保数据一致性),再调用Foo2的耗时方法,让耗时操作完全脱离事务上下文。
内容的提问来源于stack exchange,提问作者oscar
相关产品推荐
相关产品推荐

