Spring Transactional 减慢了整个流程 [英] Spring Transactional slows down complete process

查看:35
本文介绍了Spring Transactional 减慢了整个流程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<块引用>

规格

Spring-orm 版本:3.2.18.RELEASE.

JDK 版本:1.8.

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

<块引用>

问题

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

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

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

<块引用>

ProcessImpl 类.

public class ProcessImpl {/*这是从MyServiceImpl调用其他事务性东西的大事务*这是您可以说的过程的起点......** 如果我们从这里删除@Transactional,这个过程会非常快* 交易时间:15 分钟* 无交易:50 秒* */@交易public void processStage(){MyServiceImpl mp = 新的 MyServiceImpl();//做一些事情mp.doWork1();//做更多的工作mp.doWork2();}}

<块引用>

MyServiceImpl 类

class MyServiceImpl{@交易公共无效 doWork1(){对象 o = doChildWork();//还有更多的东西//调用其他类服务和dao层}@交易公共无效 doWork2(){//一些东西doChildWork2();doChildWork();//更多的工作}@交易公共对象 doChildWork(){返回新对象();//假设,我正在返回列表和其他集合的东西}@交易公共对象 doChildWork2(){返回新对象();//假设,我正在返回列表和其他集合的东西}}

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

解决方案

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

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

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

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

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

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

<块引用>

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

不,它会在忽略所有注释的情况下正常工作.doWork2() 中对 doChildWork()doChildWork2() 的调用将被视为标准的 java 调用(spring 不能添加任何 "只要您直接调用它们,就可以对它们进行魔法").

I am trying to analyze a situation where I have two classes. One class is ProcessImpl which is starting point and internally calls other child transactions.I dont know whats going wrong. The processImpl is importing some stuff and writing related data to database.

Specs

Spring-orm version : 3.2.18.RELEASE.

JDK version : 1.8.

Db : H2 (on any db same performance is recorded).

Issue

If I remove @Transactional from ProcessImpl.processStage() the process takes ~ 50 seconds If I keep @Transactional from ProcessImpl.processStage() the process takes ~ 15 minutes. Dont know why this is happening. I have been trying to solve this issue since long but no luck. Please have a look at code below.

Requirement: The complete processStage() should complete or rollback completely, even if one of child transactions fail.

Fyi : I also get lot of messages like : "Participating in existing transaction". Tried to get over this by adding propagation=Propagation.NESTED to processStage() but did not work.

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
    }

}

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

解决方案

It is hard to guess what exactly is happening in your code, however these are the possible problems:

Lock on DB level. This could happen when you update the same DB object within doWork1() and doWork2(). Since both of the methods are performed within one transaction the updates done inside doWork1() will not be committed until doWork2() is completed. Both the methods might try to lock the same DB object and wait for it. Technically it could be any DB object: row in a table, index, whole table, etc.

Analise your code and try to find what could be locked. You can also look into DB transaction log while the method is running. All popular DBs provide functionality that helps to find problematic places.

Slow down during Hibernate context refresh. In case when you update too many objects ORM engine (lets say Hibernate) has to sink them and keep them in memory. Literally Hibernate must have all old states and all new states of updated objects. Sometimes it does this not in an optimal way.

You can indicate this using debug. Try to find the slowest place and check what exactly is being invoked there. I might guess that it slows down when hibernate updates state of the cache.

One more issue. I see that you create MyServiceImpl using constructor during processStage(). I'd recommend you to replace this code by spring autowiring. First of all the way you're using it is not the way it was designed to be used, but theoretically that could also somehow influence on the execution.

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

No, it will work just fine ignoring all annotations. Calls of doChildWork() and doChildWork2() inside doWork2() will be treated as standard java calls (spring is not able to add any "magic" to them as long as you're invoking them directly).

这篇关于Spring Transactional 减慢了整个流程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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