62

我有一个具有propagation = Propagation.REQUIRES_NEW事务属性的方法:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void createUser(final UserBean userBean) {
    //Some logic here that requires modification in DB
}

此方法可以同时调用多次,并且对于每个事务,如果发生错误,则回滚(独立于其他事务)。

问题是这可能会强制 Spring 创建多个事务,即使另一个事务可用,并且可能会导致一些性能问题。


Java doc ofpropagation = Propagation.REQUIRED说:Support a current transaction, create a new one if none exists.

这似乎解决了性能问题,不是吗?

回滚问题呢?如果新方法调用在使用现有事务时回滚怎么办?这不会回滚整个事务,即使是以前的调用?

[编辑] 我想我的问题还不够清楚:

我们有数百个客户端连接到我们的服务器。

对于每个客户端,我们自然需要发送有关事务的反馈(OK 或异常 -> 回滚)。

我的问题是:如果我使用REQUIRED,是否意味着只使用了一个事务,如果第 100 个客户端遇到问题,第一个客户端的事务也会回滚?

4

2 回答 2

97

仅当从事务上下文调用方法时,使用REQUIRES_NEW才相关;当从非事务上下文中调用该方法时,它的行为将完全一样REQUIRED- 它将创建一个新事务。

这并不意味着您的所有客户端只会有一个事务 - 每个客户端将从非事务上下文开始,并且一旦请求处理达到 a @Transactional,它将创建一个新事务。

因此,考虑到这一点,如果 usingREQUIRES_NEW对于该操作的语义有意义——我不会担心性能——这将是教科书式的过早优化——我宁愿强调正确性和数据完整性,并担心性能指标一旦确定后的性能收集,而不是之前。

On rollback - using REQUIRES_NEW will force the start of a new transaction, and so an exception will rollback that transaction. If there is also another transaction that was executing as well - that will or will not be rolled back depending on if the exception bubbles up the stack or is caught - your choice, based on the specifics of the operations. Also, for a more in-depth discussion on transactional strategies and rollback, I would recommend: «Transaction strategies: Understanding transaction pitfalls», Mark Richards.

于 2012-10-24T15:46:39.913 回答
13

如果您确实需要在单独的事务中执行此操作,则需要使用REQUIRES_NEW并忍受性能开销。注意死锁。

我宁愿以另一种方式做:

  • 在 Java 端验证数据。
  • 在一个事务中运行所有内容。
  • 如果数据库方面出现任何问题 -> 这是数据库或验证设计的重大错误。回滚所有内容并抛出严重的顶级错误。
  • 编写好的单元测试。
于 2012-10-24T14:37:44.980 回答