Spring交易中REQUIRES_NEW和NESTED传播行为的差异 [英] Differences in behaviour of REQUIRES_NEW and NESTED propagation in Spring transactions

查看:352
本文介绍了Spring交易中REQUIRES_NEW和NESTED传播行为的差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

序言

首先:

它不是> require_new和春季交易中的嵌套传播-我读了它,但没有找到我的问题

It is not duplicate of Differences between requires_new and nested propagation in Spring transactions - I read it but I didn't found answer to my question

问题:

在阅读了主题之后,我提到我理解了物理交易次数的传播水平之间的主要区别:
2个数据库事务-用于REQUIRES_NEW的外部方法和内部方法
1 db事务-用于NESTED的外部方法和内部方法.如果基础数据库不支持保存点,它将无法正常工作

After reading topic I mentioned I understood that main difference between propagation levels in count of physical transactions:
2 db transactions- for REQUIRES_NEW for outer and for inner method
1 db transaction - for NESTED for outer and for inner method. It will not work if underlying database doesn't support savepoints

但是,从我的角度来看,如果逻辑上看来,逻辑将是相同的.

But looks like logic will be the same from my point if view.

如何理解在实践中使用哪个级别?有什么用例可以理解吗?方便的行为差异例子吗?

How to understand which level to use in practise? Any use cases to understand it? Handy examples of behavioural differences?

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

P.S.
I suppose there are some visibility for other transactions differences because different transaction commit time.

P.S.2

我还认为存在性能差异:

Also I suppose there are performance difference:

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

@Transactional
public void inner(){
   //some logic
}

在这种情况下,NESTED会更好,因为需要进行1次长时间的物理交易,而不是100500 + 1

For that case NESTED will be better because of 1 long physical transaction instead of 100500+1

推荐答案

在您的示例中,如果inner()具有:

As it stands in your example, if inner() had:

@Transactional(propagation=Propagation.REQUIRES_NEW)
public void inner(){
   //some logic
}

然后,如果它从outer()循环中的第二个调用引发异常,则从第一个调用进行的更改将已经提交-通过其REQUIRES_NEW.

Then if it threw an exception from the second call in the outer() loop, the changes from the first call would have already been committed - by its REQUIRES_NEW.

如果inner()具有:

@Transactional(propagation=Propagation.NESTED)
public void inner(){
   //some logic
}

然后,从第一个调用开始的更改将被回滚-因为outer()中没有catch块.

Then the changes from the first call would be rolled back - because there is no catch block in outer().

inner()上的传播级别真正开始起作用的点是outer()循环是否要处理inner()中的异常:

The point where the propagation level on inner() really starts to matter is if the outer() loop is going to handle exceptions in 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
}

很显然,REQUIRES_NEWNESTED都只会保留成功的inner()调用中的更改.但是关键的区别在于,对于NESTED,如果outer()随后发生故障,仍然可以将其全部丢弃.

Clearly both REQUIRES_NEW and NESTED would only keep changes from the successful inner() calls. The key difference though is that with NESTED, there is still the option to throw it all away if there is a subsequent failure in outer().

正如您所说,另一个因素是可伸缩性-某些数据库可能不欣赏NESTED传播的父事务的大小.

As you say, the other factor is scalability - some databases may not appreciate the size of the parent transaction with NESTED propagation.

另外,也许值得一说-尽管我怀疑它只是为了使示例清晰.直接调用this.inner()会绕过Spring事务处理顾问程序.需要允许它注入一个'advised bean',以允许@Transactional注释在调用之前和之后都发挥其魔力-例如nextAutowiredBean.inner().

Also, it might be worth saying - though I suspect it was just aiming for clarity in the example. Calling this.inner() directly is bypassing the Spring transaction advisor. It needs to be allowed to inject an 'advised bean' to allow the @Transactional annotation to do its magic before and after the call - e.g. nextAutowiredBean.inner().

这篇关于Spring交易中REQUIRES_NEW和NESTED传播行为的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆