Allow the auto-commit resolution to be configurable for RESOURCE_LOCAL transactions

Description

For RESOURCE_LOCAL transactions, the Connection acquisition is not really delayed until the first Statement is needed to be executed because a Connection is acquired right after the Transaction has started since we need to read the auto-commit flag.

However, if we know that we configured the underlying DataSource to set the auto-commit value to an explicit value, then we should provide a Hibernate configuration property which says what's that value so that we don't have to resolve it for every Connection that we fetch from the DataSource.

By default, we fall back to the current behavior. But if the users want to optimize this process, they can provide that configuration property and bypass the check.

Environment

None

Activity

Show:
Vlad Mihalcea
March 7, 2017, 8:18 PM

The Transaction#begin is important for a JPA provider perspective as we can build a transaction context. However, for RL, there is no equivalent on the Connection interface, and so we just call the auto-commit to false:

However, to quote the JavaDocs:

If setAutoCommit is called and the auto-commit mode is not changed, the call is a no-op.

Steve Ebersole
March 7, 2017, 9:34 PM

For perspective, this is something we discussed back as far as 10 years ago... specifically about delaying the acquisition of the Connection beyond what we do even still today to cater to micro-benchmarks. We decided that catering to micro-benchmarks was silly as it does not match real-world scenarios.

But why would any of this matter? Your claim is that the application begins a transaction (a transactional method is the same thing) but does not want to acquire a Connection. I'll assert that this effects an extremely small population and I'll even go further to question the validity of this use case.

The application chooses to start a transaction. Why can't it simply chose to not start the transaction?

At the same time, if this is something everyone agrees we should do and you feel strongly enough about it and want to put in the effort of adding yet another config knob and document such a thing, then I'd add a few caveats:

  1. this new setting should default to whatever hibernate.connection.autocommit is set to

  2. IMO this really entails a whole new "Connection management" scheme where an auto-commit Connection is auto-released under the same circumstances as what we do under JTA transactions. That would be the logical continuation of your thought... which specific Connection is used is actually completely irrelevant and we could aggressively release the Connections back to the provider.

Vlad Mihalcea
March 8, 2017, 6:35 AM

But why would any of this matter? Your claim is that the application begins a transaction (a transactional method is the same thing) but does not want to acquire a Connection. I'll assert that this effects an extremely small population and I'll even go further to question the validity of this use case.

It's indeed intended for high-performance use cases only. The advantage of delaying the connection acquisition is that you reduce the time interval a connection is leased by any given transaction. This is desirable since the number of connections available for every front-end application is limited, especially when you auto-scale due to a sudden traffic spike. Therefore, the shorter the connection lease time, the more transactions can be accommodated in a time unit.

The application chooses to start a transaction. Why can't it simply choose to not start the transaction?

As a general rule, this is a very good approach. That's also why I said that we shouldn't change the default mechanism. My idea is to allow the user to explicitly choose to delay it until he really needs the connection.

this new setting should default to whatever hibernate.connection.autocommit is set to

That makes sense. But this is only applicable to DriverManagerConnectionProvider and c3p0 ConnectionProvider since it's not taken into consideration when we use an external DataSource.

IMO this really entails a whole new "Connection management" scheme where an auto-commit Connection is auto-released under the same circumstances as what we do under JTA transactions. That would be the logical continuation of your thought... which specific Connection is used is actually completely irrelevant and we could aggressively release the Connections back to the provider.

That would be desirable if database connections would support transaction multiplexing. However, even if the JTA specs demand it, in reality, even XA drivers don't always support it. To the day, I don't think there are many RDBMS capable of operating with multiple concurrent transactions on the same connection. For this reason, even if we aggressively release a connection on a RL transaction, the connection pool will most likely roll it back as illustrated by HikariCP source code.

Steve Ebersole
April 13, 2017, 4:16 PM

Just to clarify something stated above... This actually NEVER affects JPA. JPA says that resource-local transaction (EntityTransaction) are only valid in non-DataSource cases.

According to JPA all other cases must use JTA (BMT or CMT) to control txn boundaries and implicitly or explicitly join the EM to that txn.

Hibernate does allow DataSource in combination with resource-local transactions.

I went ahead and commited the proposed PR with some modifications - specifically logged warnings and warnings in the documentation about enabling this "for perf reasons" when the DataSource/connection-pool are not configured to disable auto-commit.

Manuel Dominguez Sarmiento
December 30, 2019, 11:00 PM

I would like to add that delaying the connection acquistion until the first statement needs to be executed has another highly interesting advantage: if the transactional method can produce its results from the L2 and/or query caches, it does not need to hit the database at all, whereas acquiring the connection at the beginning and holding it until the end both consumes unnecessary connection resources, and requires extra network roundtrips to the database. The performance difference in applications with well-tuned caches could be dramatical.

Fixed

Assignee

Vlad Mihalcea

Reporter

Vlad Mihalcea

Fix versions

Labels

None

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

backportDecision

None

Affects versions

Priority

Major
Configure