java - Spring Transactional 减慢了整个过程

标签 java spring transactions transactional spring-orm

我正在尝试分析我有两个类(class)的情况。一类是 ProcessImpl,它是起点并在内部调用其他子事务。我不知道出了什么问题。 processImpl 正在导入一些东西并将相关数据写入数据库。

Specs

Spring-orm 版本:3.2.18.RELEASE。

JDK 版本:1.8。

Db:H2(在任何数据库上都记录了相同的性能)。

Issue

如果我从 ProcessImpl.processStage() 中删除 @Transactional,该过程需要 ~ 50 秒 如果我从 ProcessImpl.processStage() 保留 @Transactional,该过程需要 ~ 15 分钟。 不知道为什么会这样。 长期以来,我一直在努力解决这个问题,但没有运气。请查看下面的代码。

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

仅供引用:我也收到很多消息,例如:“参与现有交易”。试图通过将 propagation=Propagation.NESTED 添加到 processStage() 来解决这个问题,但没有成功。

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

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
    }

}

此外,这里会出现自调用问题,这在事务性中是不可取的吗?

最佳答案

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

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

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

在 Hibernate 上下文刷新期间放慢速度。 如果您更新太多对象,ORM 引擎(假设是 Hibernate)必须将它们下沉并保存在内存中。从字面上看,Hibernate 必须具有更新对象的所有旧状态和所有新状态。有时它不是以最佳方式执行此操作。

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

还有一个问题。我看到您在 processStage() 期间使用构造函数创建了 MyServiceImpl。我建议你用 spring Autowiring 来替换这段代码。首先,您使用它的方式不是它的设计使用方式,但理论上这也会以某种方式影响执行。

will I get self invocation issue, which is not advisable in Transactional?

不,忽略所有注释也能正常工作。在 doWork2() 中调用 doChildWork()doChildWork2() 将被视为标准 java 调用(spring 无法添加任何“魔法”,只要您直接调用它们即可)。

关于java - Spring Transactional 减慢了整个过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46214484/

相关文章:

sql - 安全递增 ID 所需的事务隔离级别

php - Laravel - 超过锁定等待超时

java - 我对 Maven 依赖项 : "org.eclipse.persistence.jpa" and "org.hibernate" 感到困惑

java - spring 上下文中的可选附加属性文件

java - "new A()"和 "A.newInstance()"有什么区别?

java - 调试 : Mergesort

java - Spring MVC : Get Unnamed Request Parameter

python - SQL 命令 SELECT 从 Postgresql 数据库中获取未提交的数据

java - AccountManager.getAccounts() 在 targetsdk > 23 中不起作用

java - 反射 - getInterfaces() 显示奇怪的接口(interface)