transaction: clear prewrite locks on rollback of a failed pessimistic commit#547
transaction: clear prewrite locks on rollback of a failed pessimistic commit#547eduralph wants to merge 3 commits into
Conversation
… commit After a 2PC commit fails at prewrite, the already-placed prewrite (2PC) locks must be rolled back. The terminal pessimistic rollback sent PessimisticRollback, which only removes LockType::Pessimistic locks, so it silently left the prewrite locks behind while still returning Ok — leaving keys locked until TTL expiry and lock resolution. Roll back a pessimistic transaction that has started committing with BatchRollback (as the optimistic path and client-go's commit cleanup do), which clears locks by start_ts regardless of type. A pessimistic transaction rolled back before commit (locks still pessimistic) continues to use the narrower PessimisticRollback. Adds a failpoint regression test. Closes tikv#545 Signed-off-by: Eduard Ralph <eduard@ralphovi.net>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughTransaction rollback now preserves whether commit reached prewrite, then uses that state to choose the rollback RPC. New failpoint tests cover lock cleanup after failed pessimistic commits and a rollback retry. ChangesPessimistic Rollback Lock Cleanup Fix
Estimated code review effort: 3 (Moderate) | ~25 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/transaction/transaction.rs`:
- Around line 704-708: The rollback path in transaction logic recomputes
`prewritten` from `get_status()` after the status has already moved to
`StartedRollback`, so retrying `rollback()` can lose the fact that the txn had
started committing. Update `transaction::Transaction`/`rollback()` to persist
this rollback mode across retries, either by storing a dedicated flag or
preserving the commit-start state before the transition, and use that saved
state when choosing between `BatchRollback` and `PessimisticRollback`.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 42469290-3135-4f7c-aa8c-2cbf4a56d457
📒 Files selected for processing (2)
src/transaction/transaction.rstests/failpoint_tests.rs
…llback rollback() recomputed `prewritten` from `get_status() == StartedCommit`, but transit_status permits re-entry from StartedRollback and a failed rollback leaves the status there. On retry, get_status() no longer reads StartedCommit, so `prewritten` became false and a pessimistic txn that had started committing fell back to PessimisticRollback, re-leaking the 2PC prewrite locks the previous commit fixed. Persist the flag on Transaction: set it when commit() enters the commit path and read it in rollback(), so it survives the StartedCommit -> StartedRollback transition and any rollback retry. Signed-off-by: Eduard Ralph <eduard@ralphovi.net>
Add a `before-rollback` failpoint in `Committer::rollback` and a regression test (`txn_pessimistic_rollback_retry_clears_prewrite_locks`) that forces the first rollback attempt to fail, then asserts the retry still clears the 2PC prewrite lock. This guards the `prewritten` flag now persisted across the StartedCommit -> StartedRollback transition: recomputing it from status on a retry would fall back to PessimisticRollback and leak the lock again. Refs tikv#545 Signed-off-by: Eduard Ralph <eduard@ralphovi.net>
After a 2PC commit fails at prewrite, the already-placed prewrite (2PC) locks must be rolled back. The terminal pessimistic rollback sent PessimisticRollback, which only removes LockType::Pessimistic locks, so it silently left the prewrite locks behind while still returning Ok — leaving keys locked until TTL expiry and lock resolution.
Roll back a pessimistic transaction that has started committing with BatchRollback (as the optimistic path and client-go's commit cleanup do), which clears locks by start_ts regardless of type. A pessimistic transaction rolled back before commit (locks still pessimistic) continues to use the narrower PessimisticRollback.
Adds a failpoint regression test.
Closes #545
Signed-off-by: Eduard Ralph eduard@ralphovi.net
Summary by CodeRabbit
commit()fails after the prewrite/2PC stage, ensuring correct cleanup of any remaining 2PC and pessimistic locks.