-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improved efficiency of ConnectionHandlingMode: deeper integration between Hibernate ORM and Agroal #7242
Comments
What are the use cases for the user to bypass JTA? Maybe distributed transactions, XA transactions, or nested transactions where the user needs fine grained control for each of its transaction. In JEE, we have |
I don't think we shuld encourage people to bypass JTA, as I can't think of very compelling reasons. My main concern is that right now we seem to allow this, could be tricky to remove it. |
Some infos. In pure JPA spec, only RESOURCE_LOCAL entityManagers are allowed to use the Is the EntityManager explicitly set to
Am I missing a case? If the EM as set to |
Reading Sanne's message, looks like I reiterated some points he made. Sorry :) |
I would suggest to split this into 2 issues.
The last item is to guarantee that the
Requirements
This is really to support cases following the bean managed transaction scenarios. |
Why have bean managed transaction though vs only the UserTransaction approach? |
In the bean managed transaction scenario the application controls the transaction boundary local to the resources in question. For the Hibernate case - For UserTransaction - it is still a JTA transaction, just controlled by the user, so resources will have to be automatically enlisted. Since deferred enlistment isn't supported by Agroal - if any resource manager (MQ, ...) - you will have to make sure that |
FWIW adding a BEFORE_COMMIT is worthwhile regardless of the outcome here.. |
right, thanks @sebersole let's start with that aspect then; I think I like Jesper's plan, some of the details can be figured out later. @barreiro could you wrap up your prototype and send an HHH PR ? |
Personally not a fan of "ordered sync" approach. We tried this once with JBoss AS and Hibernate and the JBoss Cache implementation. It was difficult to get right in all situations. Plus, Quarkus could handle this itself by registering a custom As for the rest, well that depends on whether Quarkus wants/needs to support non-JTA transactions. I can't answer that |
My guess regarding your trouble with |
@Sanne A lot of what you propose in |
That's not strictly true - it depends on the configuration. If one has configured JTA then Hibernate will start a Transaction/UserTransaction as opposed to using Connection's auto-commit
However, this would require |
Right but what would be the value or use case for a user to use the |
Regarding the ordered synch:
Regarding the plan to support non-JTA transaction: agree with Jesper, let's consider to take the existing undefined support out; we can always plan to reintroduce later. Regarding |
Regarding releasing after the transaction rather than before... Maybe not a bug per-se, but I would not call it the best option. Releasing during the before-commit phase is definitely a better approach imo and should at least be an option as we are discussing here |
There's one, which is the transaction-less use case. The techempower benchmark badly needs it :( |
sorry I mean setAutoCommit(false). true is the default so it works I suppose, does it? |
@Sanne @barreiro Not sure if this was considered in Agroal design, but I may have found another possible issue with the Connection Wrapper. If you set https://docs.oracle.com/en/java/javase/11/docs/api/java.sql/java/sql/ResultSet.html#HOLD_CURSORS_OVER_COMMIT, because of the Connection Wrapper, Agroal will not honour the ResultSet type and will just close the connection on commit (like designed) and completely ignore the flag. |
It's been a while and this could solve other issues, so I'll try to revive this... From my understanding, switching the The only remaining concerns are:
Unless someone disagrees, I'll go ahead and submit a PR that removes support for |
@yrodiere yes switching to |
DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT, on top of being less efficient, also leads to resource leaks (that are caught by Agroal, but still). Signed-off-by: Yoann Rodière <yoann@hibernate.org>
DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT, on top of being less efficient, also leads to resource leaks (that are caught by Agroal, but still). Signed-off-by: Yoann Rodière <yoann@hibernate.org>
DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT, on top of being less efficient, also leads to resource leaks (that are caught by Agroal, but still). Signed-off-by: Yoann Rodière <yoann@hibernate.org>
DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT, on top of being less efficient, also leads to resource leaks (that are caught by Agroal, but still). Signed-off-by: Yoann Rodière <yoann@hibernate.org>
DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT, on top of being less efficient, also leads to resource leaks (that are caught by Agroal, but still). Signed-off-by: Yoann Rodière <yoann@hibernate.org>
DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT, on top of being less efficient, also leads to resource leaks (that are caught by Agroal, but still). Signed-off-by: Yoann Rodière <yoann@hibernate.org>
DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT, on top of being less efficient, also leads to resource leaks (that are caught by Agroal, but still). Signed-off-by: Yoann Rodière <yoann@hibernate.org>
DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT, on top of being less efficient, also leads to resource leaks (that are caught by Agroal, but still). Signed-off-by: Yoann Rodière <yoann@hibernate.org>
After having switched the Hibernate ORM's
PhysicalConnectionHandlingMode
toDELAYED_ACQUISITION_AND_RELEASE_AFTER_TRANSACTION
as I believed it would have been a more efficient choice, I had to revert it as short term fix for #6770 . This is to track the propert fix.The problem
Hibernate ORM's is assuming it deals with the "physical" connection, as the name of the property suggests, but when there is a running transaction Agroal doesn't return the raw connection but a wrapper.
At transaction commit, Agroal verifies that all wrappers which depend on the currenty physical connection have been closed first - otherwise it's assuming one has "escaped" the scope of its indended lifespan and it logs a warning about a possible leak.
At high level, assuming a JTA environment (like Quarkus normally is):
In such a scenario, if Hibernate's EntityManager [or Session] isn't closed before the TX is committed, the connection wrapper will still be open - hence the warning log.
A simple way forward is to expect the EntityManager to have been closed before commit, but this is counter-intuitive if we allow code looking like:
One problem of such code is that we seem to allow
em.getTransaction()
, which is normally not allowed in JTA (it's supposed to throw anIllegalStateException
) as one should either let the container manage transactions, or explicitly request a reference to a UserTransaction. Clearly a benefit of letting the container handle such details is that it can control the lifecycle of the various parties and cleanup stuff in some controlled order.Question
What should
EntityManager.getTransaction()
do ? Is the current semantics reasonable?N.B. if I understood the Agroal experts correctly, a single Agroal connection pool is either configured to integrate with JTA or not: if JTA integration is enabled, it will require a running transaction for any new connection request.
Also Jesper reminds: "we can't support deferred enlistement, like JCA can"
Some Ideas
Some notes from previous brainstorming:
Implement a new DELAYED_ACQUISITION_AND_RELEASE_BEFORE_TRANSACTION
We could have Hibernate ORM release the connection just before the commit.
@barreiro already created a branch: hibernate/hibernate-orm@master...barreiro:before-completion
This seems simple and would be rather effective, but @jesperpedersen is warnings us against the use of interposed Synchronization(s); in WildFly for example they had to guarantee ordering to avoid some more complex problems with them.
[Q: is the use of Synchronization really a problem? ORM is already registering one, it seems Luis's code is merely using the existing synchronization]
Allow Hibernate ORM to bypass Agroal's safety net.
I'm not suggesting we should, but it would be interesting to consider this: both Agroal and Hibernate ORM seem to implement strict measures against leaking of resources. For sake of performance we should allow the two components to trust each other, and avoid duplicating checks.
It's tempting to have ORM access the real "physical" connection and:
[I'm aware that resource tracking of statements can be disabled - but if we disable it on the pool, then it's also disabled for user code using the pool directly, which is likely not a good idea]
I suspect the strongest argument against this would be that Agroal itself would need to expose an unsafe API. Maybe not my best idea? But it would be nice to allow a "friend framework" some deeper integration for sake of efficiency, as it would allow for more optimisations than just solve this specific issue.
For example, both Agroal and Hibernate ORM perform #clearWarnings on the connection before returning it - I noticed it's actually not such a cheap operation on some drivers, even when there's no warnings to clear.
Have Agroal change design?
Agroal has chosen to implement this "Connection Wrapper" approach as a way to model the fact that each resource in an XA transaction needs to have reached the "end state" for the operations on each resource before the commit is allowed to proceed.
However, the usage of Hibernate ORM is not illegal per se: it is in a de-facto "end state" as it will no longer issue any statement on the connection - it simply hasn't really closed it yet.
This makes me think that perhaps the Connection Wrapper design in Agroal is too strict: there might be other ways to model the end state? For example, the wrapper could simply disallow any further use of the underlying connection rather than expecting it to have been closed already.
But first
The ideas above all seem viable, and are not mutually exclusive. Personally I think I prefer @barreiro 's proposal to introduce a new before-commit release mode in ORM - and yet we could also optimise the Agroal/ORM integration by removing some more redundant checks.
And yet.. we probably need to consider first what are the implications of allowing people to use
EntityManager.getTransaction()
: honestly that's confusing me a bit.The text was updated successfully, but these errors were encountered: