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
.timeout(ms, {cancel: true})
for with queued queries in transaction
#4415
Comments
This bug was originaly mentioned in #2211 (comment), where @elhigu commented:
|
We could use
And also the final attempt to
However I didn't manage to handle those errors properly, to raise |
I created a PR #4416 with an attempt to fix it by removing the timeouted queries from the driver queue. However the solution messes with the driver internal queue quite a bit, so I'm not sure it's safe. But I haven't come up with any other working solution yet. |
I mean... is there a way to setup mysql to also automatically rollback transaction if any of the queries fail. Current functionality is consistent with postgresql, since any failing query (for example insert conflict) will rollback the postgresql transaction, but it won't rollback in mysql. So wouldn't making timeout to be a special case rolling back in mysql would make knex behaviour more inconsistent? If consistency between mysql and postgresql is what you are looking for, then you could configure postgresql transactions to not rollback in case of failing queries? |
I'm still not convinced that this behaviour even should be changed. |
Not that I'm aware of. But even if there is such option, the timeouted query cancelation should work reliably even without using this option.
Not really. It would be nice for MySQL and Postgres to behave consistently, but it is probably not possible, as their query cancellation commands behave differently. My goal it to make cancelation of timeouted queries working reliably also in transactions on both databases. That is, when a query times out, it is cancelled. But not necessarily the same way or with the same impact on the transaction or the connection on both databases. Currently, after fixing #4324, cancelation of timeouted queries works on MySQL reliably in transactions only if the queries are run one by one from a single coroutine. But it fails in some cases when queries are started simultaneously from multiple parallel coroutines. In such case they are queued in the driver and wait for their turn. And if they timeout while they are queued, they will never get cancelled. Before fixing #4324 cancelation of timeouted queries didn't work at all in transactions, so I wasn't aware of this corner case (or perhaps a race condition). |
Sorry, we probably didn't understand each other. No, I don't want to rollback the transaction in MySQL, I just want to cancel timeouted queries. And yes, preferably without closing the transaction nor the connection if possible. Btw, even in Postgress the user may still resurrect their transaction after it is marked failed. They can create a savepoint before the slow query, try run it, and roll back to the savepoint in case the query times out. So it is good to keep the connection (and the transaction) open even in MySQL. We just need to find a reliable way how to cancel a query, even in the case it times out while still queued. |
Another example to demonstrate the problem:
Expected behaviour in MySQL
Current behaviour with MySQL
The problem is that |
Ah right... looks like there wasn't any switch in DB for that, but only setting for
|
Environment
Knex version: current
master
Database + version: MySQL - any version
OS: any
Bug
If we queue multiple slow queries with timeouts in a transaction, not all of them will get cancelled after timeouting. E.g.:
As the queries are in the transaction, they get queued in the driver which sends them to DB one by one. As all queries will timeout at approximately the same time, all their
KILL QUERY ?
commands will be also sent to DB at approximately the same time. Therefore they will kill only the first query. After that the driver sends the second query to DB which will be never killed, as its timeout already elapsed and itsKILL QUERY ?
command was already sent.The problem occurs only on MySQL. Postgres marks the transaction failed after killing the query, therefore any further queries in the same transaction will immediately fail.
I guess we should simulate the same behaviour on MySQL as well. Either by removing the timeouted queries from the driver queue, or by rolling back the transaction with the killed timeouted query.
I've written a test to replicate this bug. It passes for Postgres and fails for MySQL: https://github.com/martinmacko47/knex/pull/4/files#diff-ef380392f7c99984959538380cd3a01631d49da7eb768b02fd71695bfb2a3febR981-R1052
The text was updated successfully, but these errors were encountered: