Spring事务中REQUIRES_NEW和NESTED传播行为的差异

gst*_*low 6 java spring transactions spring-transactions

前言

首先:

与Spring事务中的requires_new和嵌套传播之间差异不重复- 我读了它,但我没有找到我的问题的答案

题:

在阅读了我提到的主题后,我理解了物理事务计数中传播级别的主要区别:
2 db事务 - REQUIRES_NEW用于外部和内部方法
1 db事务 - NESTED用于外部和内部方法.如果底层数据库不支持保存点,它将无法工作

但是看起来逻辑从我的观点来看是相同的.

如何理解在实践中使用哪个级别?任何用例了解它?方便的行为差异的例子?

PS
我认为其他事务差异有一些可见性,因为不同的事务提交时间.

PS2

另外我认为有性能差异:

@Transactional
public void outer(){
    for(int i=0;i<100500;i++){
        inner();
    }   
}

@Transactional
public void inner(){
   //some logic
}
Run Code Online (Sandbox Code Playgroud)

对于那种情况,NESTED会更好,因为1长的物理交易而不是100500 + 1

df7*_*899 5

就您的示例而言,如果inner()有:

@Transactional(propagation=Propagation.REQUIRES_NEW)
public void inner(){
   //some logic
}
Run Code Online (Sandbox Code Playgroud)

然后,如果它在outer()循环中的第二次调用中抛出异常,则第一次调用中的更改将已经提交 - 由其REQUIRES_NEW.

如果inner()有:

@Transactional(propagation=Propagation.NESTED)
public void inner(){
   //some logic
}
Run Code Online (Sandbox Code Playgroud)

然后将回滚第一次调用的更改 - 因为outer().


传播级别inner()真正开始重要的一点是outer()循环是否要处理以下异常inner()

@Transactional
public void outer() {
    for (int i = 0; i < 100500; i++) {
        try {
            inner();
        } catch (Exception ex) {
            // Report and continue
        }
    }
    // Something else that could fail
}
Run Code Online (Sandbox Code Playgroud)

显然,两者REQUIRES_NEWNESTED只保留从成功改变inner()通话。但关键的区别在于,NESTED如果outer().

正如您所说,另一个因素是可扩展性 - 某些数据库可能不会通过NESTED传播来理解父事务的大小。


此外,这可能值得一提——尽管我怀疑它只是为了让示例更加清晰。this.inner()直接调用是绕过 Spring 事务顾问程序。它需要被允许注入一个“被建议的 bean”,以允许@Transactional注释在调用之前和之后发挥它的魔力——例如nextAutowiredBean.inner()


asc*_*erk 4

我看到的巨大差异:

如果是嵌套的:

  • 如果外部事务回滚,则嵌套事务也会回滚。
  • 可见性:如果数据库执行同时很常见的 MVCC,
    • 嵌套 tra 会看到外部 tra 之前的更改。
    • 提交外部 tra 后,嵌套 tra 的更改将被视为已提交并且对其他 tra 可见。
  • 性能:请注意,外部事务的工作集会被内部事务扩展。因此,更多的锁、更多的 MVCC 原像存储、更长的重做日志条目。

如果是requires_new:

  • 如果外层事务回滚,则外层事务回滚时,内层事务的更改不会回滚。
  • 可见性:对于同时相当常见的 MVCC,
    • 内部 tra 将看不到尚未提交的外部 tra 所做的更改。
    • 在此内部 tra 提交之后,甚至在外部 tra 提交之前,嵌套 tra 的更改将被视为已提交并对其他 tra 可见。锁较少,但由于外部操作的提交较多,重做锁中的记录较多。

就性能而言,如果其他因素不重要,您可以在交易规模和交易数量之间找到收支平衡。恕我直言,如果嵌套比 require_new 更快,那么这个问题没有一般答案。