-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
DefaultSqlSession doesn't ROLLBACK on close after SELECT #2363
Comments
Hello @ivanr , I could be wrong, but this seems to be an issue that should be taken care of by the connection pool. |
indeed!! |
The connection pool provided by MyBatis rollback real connection at before returning it into pool. Other major OSS connection pool implementations rollback a real connection at before returning it by default behavior. |
@harawata I have so far only looked at the logic in DefaultSqlSession. I will do another check, this time with a connection pool. It may take me some time to respond because of the upcoming holidays, but I will get back to you. Thank you. |
Reading your comments on #2156 (comment) , I think your issue may also be resolved by #2741 .
Please let me know if you think it's a different issue. |
@harawata Thank you. With Prompted by this comment I went back to test the exact behaviour. I observed that, when a session is being closed, a commit is executed if the session is not dirty. Tracing through the code, I think this is the code in CachingExecutor that calls commit:
Regarding MyBatis's tracking of "dirty" transactions and having to explicitly force commits, etc, what's the rationale behind it? Is it documented anywhere? I think it would be easier for everyone if commit and rollback were just that, and if a rollback were used before a connection is returned to a pool. Given the above code, where either commit or rollback are executed, why is commit preferred despite the potential unwanted side-effects? Are there any databases where commits are much faster? NOTE I edited this comment after realising the the commit is seemingly not run by the connection pool. |
Hello @ivanr , MyBatis does not explicitly call If the transaction is committed on close, you probably are using "JDBC" transaction manager.
And some drivers (including pgjdbc) internally commit the transaction when Please see the doc for how to change the default behavior. I don't know why
(In #2741, I added "select with p.s. |
@harawata Yes, you're right about that. I actually had Thank you for your help :) |
I've been reading the code of DefaultSqlSession and I believe that transactions are not correctly closed when close() is called. The current behaviour is that rollback is submitted only for INSERT/UPDATE/DELETE statements, but not SELECT. Because there is no rollback, the same transaction continues and multiple logical operations may be called in the same transaction, with unpredictable side-effects. For example, a SELECT... FOR UPDATE could create a lock that is not released. Advisory locks wouldn't be released.
The correct behaviour is to ROLLBACK is any one query, including SELECTs.
EDIT The same problem exists with calling close() and rollback(). In our case, we always force commits and rollbacks, but there's no such option for the close operation.
MyBatis version
3.5.7
Database vendor and version
Possibly all, but I have Postgres in mind.
Test case or example project
None.
Steps to reproduce
With connection pooling configured, create a session object, submit some SELECT queries, then close the session without committing or rolling back.
Expected result
Closing SQL session will ROLLBACK the connection.
Actual result
There is no ROLLBACK. EDIT 2022-12-03
Transaction remains active in idle state until the connection is reused.Transaction is committed.The text was updated successfully, but these errors were encountered: