Skip to content

fix(mysql): roll back a transaction cancelled during BEGIN - #4468

Open
chenty2333 wants to merge 1 commit into
transact-rs:mainfrom
chenty2333:mysql-cancelled-begin
Open

chenty2333 wants to merge 1 commit into
transact-rs:mainfrom
chenty2333:mysql-cancelled-begin

Conversation

@chenty2333

Copy link
Copy Markdown

Does your PR solve an issue?

fixes #4467

This is the MySQL counterpart of #4394. MySqlTransactionManager::begin raised transaction_depth only after the BEGIN round trip and had no drop guard, so a begin() cancelled during that round trip queued no ROLLBACK (start_rollback is a no-op at depth 0), and the pool handed the connection, still inside the transaction, to the next borrower.

The change follows #4394: claim the depth before the round trip, unwind it if the BEGIN did not take, and add the same Rollback guard so a dropped future queues a ROLLBACK at the claimed depth. With the existing Transaction::drop guard, a cancelled top-level begin() now queues exactly one ROLLBACK; at depth 0 the second start_rollback is a no-op. Nested begin() now behaves as on Postgres after #4394; the enclosing-level rollback described in #4445 is unchanged by this PR.

it_rolls_back_a_transaction_cancelled_during_begin in tests/mysql/mysql.rs cancels begin_with("BEGIN; SELECT SLEEP(2);") after 300 ms, then checks that an autocommit insert through the pool is visible from another connection. It fails on main (0 rows) and passes with the fix. The MySQL test suite (any,mysql,mysql-rsa,macros,migrate,_unstable-all-types,runtime-tokio,tls-none) passes against MariaDB 11.4; cargo fmt and the CI cargo clippy invocation are clean.

Is this a breaking change?

No. A cancelled top-level begin() now queues a ROLLBACK, and a BEGIN that fails with an error queues one too (as on Postgres since #4394); MySQL accepts ROLLBACK outside a transaction without an error.

Claim transaction_depth before the BEGIN round trip and add a Rollback
guard, as transact-rs#4394 did for Postgres, so a begin() dropped mid-flight queues a
ROLLBACK instead of returning the connection to the pool inside a
transaction.

Fixes transact-rs#4467.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MySQL: cancelling begin() leaves the pooled connection inside a transaction

1 participant