Spring Transactional减慢了整个过程

swa*_*ntu 5 java spring transactions transactional spring-orm

我试图分析一下我有两个班级的情况.一个类是ProcessImpl,它是起点并在内部调用其他子事务.我不知道什么是错误的.processImpl正在导入一些东西并将相关数据写入数据库.

眼镜

Spring-orm版本:3.2.18.RELEASE.

JDK版本:1.8.

Db:H2(记录任何db相同的性能).

问题

如果我@TransactionalProcessImpl.processStage()过程中删除需要~50秒 如果我保持@TransactionalProcessImpl.processStage()过程需要〜15分钟.不知道为什么会这样.我一直试图解决这个问题,但没有运气.请看下面的代码.

要求: 完成processStage()应完成或完全回滚,即使其中一个子事务失败.

Fyi:我也收到很多消息:"参与现有交易".试图通过添加propagation=Propagation.NESTEDprocessStage()但没有工作来克服这个问题.

ProcessImpl类.

public class ProcessImpl {

    /*This is the big transaction that calls other transactional stuff from MyServiceImpl
    * This is starting point you can say for the process...
    * 
    * If we remove @Transactional from here the process is lightning fast 
    * With transactional : 15minutes
    * Without transactional : 50 seconds
    * */
    @Transactional
    public void processStage(){
        MyServiceImpl mp = new MyServiceImpl();
        //do some stuff
        mp.doWork1();

        //do more work
        mp.doWork2();

    }

}
Run Code Online (Sandbox Code Playgroud)

MyServiceImpl类

class MyServiceImpl{

    @Transactional
    public void doWork1(){
        Object o = doChildWork();
        // and more stuff
        //calls other class services and dao layers
    }

    @Transactional
    public void doWork2(){
        //some stuff
        doChildWork2();
        doChildWork();
        //more work
    }

    @Transactional
    public Object doChildWork(){
        return new Object(); //hypothetical, I am returning list and other collection stuff
    }

    @Transactional
    public Object doChildWork2(){
        return new Object(); //hypothetical, I am returning list and other collection stuff
    }

}
Run Code Online (Sandbox Code Playgroud)

此外,我将在这里获得自我调用问题,这在Transactional中是不可取的?

Sas*_*ota 7

很难猜测你的代码到底发生了什么,但是这些是可能的问题:

锁定数据库级别。 当您在doWork1()和 中更新相同的数据库对象时,可能会发生这种情况doWork2()。由于这两种方法都在一个事务中执行,因此在完成doWork1()之前不会提交内部完成的更新doWork2()。这两种方法可能会尝试锁定同一个 DB 对象并等待它。从技术上讲,它可以是任何 DB 对象:表中的行、索引、整个表等。

分析您的代码并尝试找出可能被锁定的内容。您还可以在方法运行时查看数据库事务日志。所有流行的 DB 都提供有助于查找有问题的地方的功能。

在休眠上下文刷新期间减慢速度。如果您更新太多对象,ORM 引擎(比如 Hibernate)必须接收它们并将它们保存在内存中。从字面上看,Hibernate 必须具有更新对象的所有旧状态和所有新状态。有时它不是以最佳方式做到这一点。

您可以使用调试来指示这一点。尝试找到最慢的地方并检查那里到底调用了什么。我可能猜测它在休眠更新缓存状态时会变慢。

还有一个问题。我看到您MyServiceImplprocessStage(). 我建议您通过弹簧自动装配替换此代码。首先,您使用它的方式不是它设计的使用方式,但理论上这也会以某种方式影响执行。

我会遇到自调用问题,这在事务中是不可取的吗?

不,它会很好地忽略所有注释。doChildWork()doChildWork2()inside 的调用doWork2()将被视为标准的 java 调用(只要您直接调用它们,spring 就无法向它们添加任何“魔法”)。