Spring Transaction Slows the Complete Process

I am trying to analyze a situation where I have two classes. One class is ProcessImpl, which is the starting point and internally invokes other child transactions. I do not know what is going wrong. ProcessImpl imports some things and writes related data to the database.

the functions

Spring version of -orm : 3.2.18.RELEASE.

JDK version : 1.8.

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

Problem

If I @Transactional from ProcessImpl.processStage() , the process takes ~ 50 seconds. If I save @Transactional from ProcessImpl.processStage() , the process takes ~ 15 minutes . I don’t know why this is happening. I tried to solve this problem for a long time, but with no luck. Please see the code below.

Requirements: The full processStage() must complete or roll back completely, even if one of the child transactions fails.

Fyi: I also get a ton of messages like: "Participating in existing transactions." Tried to overcome this by adding propagation=Propagation.NESTED to processStage() , but didn't work.

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

Class 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 } } 

Also, here I get a self-starting problem, what is not recommended in Transactional?

+5
source share
2 answers

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

DB level lock. This can happen if you update the same DB object in doWork1() and doWork2() . Since both methods execute in a single transaction, updates made inside doWork1() will not be executed until doWork2() . Both methods may try to lock the same database object and wait for it. Technically, this can be any DB object: a row in a table, an index, an entire table, etc.

Analyze your code and try to find what you can block. You can also view the database transaction log while the method is running. All popular databases provide functionality that helps find problem areas.

Slow down during Hibernate context update. If you update too many objects, the ORM engine (say, Hibernate) should flood them and store them in memory. Literally, Hibernate should have all the old states and all new states of the updated objects. Sometimes this makes it completely non-optimal.

You can specify this using debugging. Try to find the slowest place and check what exactly is called there. I can guess that it slows down when hibernate updates the state of the cache.

One more problem. I see that you create MyServiceImpl using the constructor during processStage() . I recommend that you replace this code with spring autowiring. First of all, how you use it is not the way it was intended to be used, but theoretically it can also affect execution.

I will get a self-starting problem, what is impractical in a transaction?

No, it will work just fine, ignoring all annotations. The calls to doChildWork() and doChildWork2() inside doWork2() will be treated as standard java calls (spring cannot add any magic to them if you call them directly).

+3
source

Any answers here will really be just (very well-informed) guesses. In such a situation, it is best to access the Java profiler and perform detailed processor level profiling to determine exactly what is happening.

I offer a great YourKit, which is commercial, but you can get a free trial.

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

0
source

Source: https://habr.com/ru/post/1271784/


All Articles