Cancel statements before closing when destroying unreturned connection after timeout #30
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Hi,
we ran into the following issue: We use c3p0 with "unreturnedConnectionTimeout", we use mysql and we have a very long running query, that triggers the "unreturnedConnectionTimeout". The query is of course a bug in the application. However, the query is not cancelled and continues - both in the application thread and the mysql server - still using resources. While c3p0 reports "0" busy connections after the message "A checked-out resource is overdue, and will be destroyed", the connection is still alive.
I traced it down to the following two threads: "http-bio-8080-exec-14" is the thread that executes the query and waits for the results. This one is actively using the database connection. The other thread is C3P0's helper thread which is trying to destroy the connection. But it's blocked inside mysql's jdbc connector while trying to get hold of the connection.
I added a call to "cancel" before closing the statement. This is implemented for the mysql connector as a "KILL QUERY " statement which terminates the connection.
This seems to be working. Of course, you get a couple of exceptions (e.g. "No operations allowed after connection closed" and hibernate "could not extract ResultSet"), but at least the
connection is released both on client and server.
The cancel is called on any "uncachedActiveStatements" - which is most times empty. There seems to be only statements in it, when the statements are indeed still active. Otherwise they have been already closed and removed. So there should be no impact on returning the connection to the pool via a regular close().
The cancel implementation in mysql connector uses a new connection, so there might be still cases, when the server wouldn't allow additional connections and cancel/KILL QUERY can't be executed.
I've observed this issue now for uncached statements. There might be a similar issue for cached statements, although the closing of the statements is deferred until the connetion is free. But the connection is not returned into the pool in time, so it can be considered as broken, and a cancel should then be called for the cached statements as well.
Is this even a problem, that should be fixed by the connection pool or should this be rather fixed by the JDBC driver (in that case, mysql)?
In order to reproduce the issue, you can use this query: "SELECT SLEEP(10000)". I got with this query the exact same behavior as with the real query.
Regards,
Andreas