-
Notifications
You must be signed in to change notification settings - Fork 18k
database/sql: cancelled context in a transaction gives a variable error #43507
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
Comments
/cc @bradfitz @kardianos |
It would be hard to change this behavior without breaking existing code. Not only that, this may be loose information that is needed. In other words, it is meaningful to know if the Tx has committed or not. You may not care, others surely will. |
Sure sure... that's why my solution was to add a field/method to sql.Tx that would record the fact that it got rolled back via the context finishing. |
is there any solution for this ? |
Lines 2249 to 2263 in 5fe3f0a
I am also puzzled by this. Generally, after |
I think extending There's code in the wild that discards the error conflating it with a cancellation, but unfortunately, this masks potentially real issues. (Especially ones where you shot yourself in the foot and ended up with an aborted transaction). |
👋 hey folks, we've been bitten by this quite a few times as well. it makes it difficult to distinguish expected "4xx-style" (canceled) errors vs "5xx-style" errors. has anyone figured out any workaround? |
Summary
When you're running a transaction with a context, and the context get cancelled, the error you get back when you go to commit is not always the same. Sometimes you see sql.ErrTxDone and sometimes you see context.Cancelled. If you commit after the context is cancelled but before database/sql rolls back the transaction in response to the context being done, then you get context.Cancelled. If database/sql finishes the rollback before you call Commit, then you get sql.ErrTxDone.
This is very confusing, because context.Cancelled is normal and expected in API handlers, but sql.ErrTxDone usually means there's a bug in the code (i.e. trying to use a transaction that's already been finished). We spent way too long at work worrying over this "bug" in our code before finally figuring out that this is just a different error sometimes returned when a context gets cancelled.
The big problem is that when you get sql.ErrTxDone, there's no way to distinguish between "hey dummy, you already called Commit or Rollback, that's a bug" and "the context you were using got cancelled, so we rolled back, no big deal".
Ideally I'd like the sql.Tx to record when it rolls back a transaction due to a cancelled context, so when I get sql.ErrTxDone, I can check that and know for sure if someone's introduced a bug, or if it's just a cancelled context.
i.e.
(or some such.... I mean, ideally I would have just had tx.Commit return context.Cancelled in the first place, but that would be a behavior change that I presume is Not Allowed)
What version of Go are you using (
go version
)?1.15.6
Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Note that if you remove the time.Sleep, you get context.Cancelled and if you leave it in there you get sql.ErrTxDone.
What did you expect to see?
"context cancelled"
What did you see instead?
"transaction already committed or rolled back"
The text was updated successfully, but these errors were encountered: