2017-09-14 102 views
5

我想分析一个情况,我有两个类。一个类是ProcessImpl,它是起点,并在内部调用其他子事务。我不知道发生了什么问题。 processImpl正在导入一些内容并将相关数据写入数据库。春季交易减缓完成过程

规格

Spring的ORM版本:3.2.18.RELEASE。

JDK版本:1.8。

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

问题

如果我从ProcessImpl.processStage()删除@Transactional过程需要50秒 如果我继续@TransactionalProcessImpl.processStage()过程需要〜15分钟。 不知道为什么会发生这种情况。 我一直试图解决这个问题,因为很长,但没有运气。请看下面的代码。

要求: 完整processStage()应该完成或完全回滚,即使儿童事务的一个失败。我也收到很多消息:“参与现有交易”。试图通过添加propagation=Propagation.NESTEDprocessStage()来解决这个问题,但没有奏效。

ProcessImpl Class。

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(); 

    } 

} 

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 
    } 

} 

而且,在这里我会得到自我调用的问题,这是不可取的事务?

+0

尝试添加'readonly'为'@ Transactional' – StanislavL

+0

我与其他的选择操作一起做大量插入在这个过程中,因此,将只读了processStage还有效吗? – swapyonubuntu

+0

不,那么readonly不是您的案例的选项 – StanislavL

回答

3

这是很难猜测什么是你的代码完全发生,然而,这是可能出现的问题:在数据库级别

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

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

在Hibernate上下文刷新过程中放慢速度。如果你更新了太多的对象ORM引擎(可以说Hibernate)必须将它们淹没并保存在内存中。从字面上看,Hibernate必须具有所有旧状态和更新对象的所有新状态。有时候这样做并不完美。

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

还有一个问题。我看到您在processStage()期间使用构造函数创建MyServiceImpl。我建议你用春天的自动装配代替这段代码。首先,你使用它的方式并不是它被设计使用的方式,但理论上这也可能影响执行。

我会得到自我调用问题,这在交易中不可取?

不,它会工作得很好,忽略所有注释。调用doChildWork()doChildWork2()里面的doWork2()将被视为标准的java调用(只要你直接调用它们,spring就不能为它们添加任何“魔术”)。

0

在这里的任何答案将只是(非常灵通)猜想。在这种情况下,要做的最好的事情就是掌握一个Java分析器并做一个详细的cpu级别分析,以确定究竟发生了什么。

我建议优秀YourKit这是商业,但你可以得到一个免费试用。

https://www.yourkit.com/docs/java/help/performance_bottlenecks.jsp

+0

已经做到了,我非常确定@Transactional会导致非常糟糕的性能结果... – swapyonubuntu