jlars62
jlars62

Reputation: 7383

Unnecessary database transactions cause slowness?

I am working in a Spring, Java, Hibernate, Postgresql environment. I am seeing some pretty severe slowness on my database. My specific question is how bad is it if I am adding Spring's @Transactional annotation to a class that contains methods that do not hit the database? In other words, they do not require a transaction. Suppose these methods are some of the more frequently used methods.

So something like this (just an example):

@Component
@Transactional
public class ProjectManager {

    public String getProjectUrl(Project project) {
         //simple logic that does not use the database
         return "/my/url/" + project.getId();
    }

}

I understand there are a lot of factors that can cause database slowness. I am just wondering if this is a huge red flag or not that big of a deal? Should I pull these methods out and put them into a different class that is not marked with @Transactional?

TIA

Upvotes: 2

Views: 446

Answers (1)

Eugene
Eugene

Reputation: 2701

First of all, your getProjectUrl method will be intercepted with spring aspect, that:

  1. Creates transaction if required
  2. Invokes your method
  3. Completes transaction

This is well-described at spring docs. Also, Spring is not smart enough to understand that method code doesn't use DB at all (as we see see in source).

So, we can definitely conclude that Spring's @Transactional causes some overhead.

But what kind of overhead?

  • Java in any case - Aspect code implements anyway
  • Depending on propagation value of @Transactional we may be forced to create physical (DB) transaction. This causes network + connection + db-side overhead.

From other side, if you remove @Transactional, you should also know that Postgres wraps ANY non-transactional SQL query in implicit transaction (docs):

PostgreSQL actually treats every SQL statement as being executed within a transaction. If you do not issue a BEGIN command, then each individual statement has an implicit BEGIN and (if successful) COMMIT wrapped around it.

Finally, the answer: Do not use @Transactional if your method does't deal with DB.

Upvotes: 4

Related Questions