我有一个具有propagation = Propagation.REQUIRES_NEW
事务属性的方法:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void createUser(final UserBean userBean) {
//Some logic here that requires modification in DB
}
此方法可以同时调用多次,并且对于每个事务,如果发生错误而不是回滚(独立于其他事务)。
问题是,这可能会迫使Spring创建多个事务,即使有另一个事务可用,也可能会导致一些性能问题。
propagation = Propagation.REQUIRED
的Java文档说:Support a current transaction, create a new one if none exists.
这似乎解决了性能问题,不是吗?
回滚问题怎么样?如果新方法调用在使用现有事务时回滚,该怎么办?即使之前的电话会不会回滚整个交易?
[编辑] 我想我的问题不够明确:
我们有数百个客户端连接到我们的服务器。
对于每个客户,我们自然需要发送有关交易的反馈(确定或例外 - >回滚)。
我的问题是:如果我使用REQUIRED
,是否意味着只使用了一个事务,如果第100个客户端遇到问题,第一个客户端的事务也会回滚?
答案 0 :(得分:65)
使用REQUIRES_NEW
仅在从事务上下文调用方法时才有意义;当从非事务性上下文调用该方法时,它的行为与REQUIRED
完全相同 - 它将创建一个新事务。
这并不意味着所有客户端只会有一个单一的事务 - 每个客户端都将从非事务性上下文开始,一旦请求处理达到@Transactional
,它就会创建一个新的交易。
因此,考虑到这一点,如果使用REQUIRES_NEW
对该操作的语义有意义 - 而不是我不担心性能 - 这会使教科书过早优化 - 我宁愿强调正确性和数据完整性一旦收集了性能指标,就会担心性能,而不是之前。
在回滚时 - 使用REQUIRES_NEW
将强制启动新事务,因此异常将回滚该事务。如果还有另一个正在执行的事务 - 根据操作的具体情况,将根据异常是否在堆栈中冒泡或被捕获而将会回滚或不回滚 - 这是您的选择。
另外,为了更深入地讨论事务策略和回滚,我建议:«Transaction strategies: Understanding transaction pitfalls», Mark Richards。
答案 1 :(得分:10)
如果您确实需要在单独的事务中执行此操作,则需要使用REQUIRES_NEW
并使用性能开销。注意死锁。
我宁愿以另一种方式去做: