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 4 commits into
Conversation
|
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 (2)
📝 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 Sequence Diagram(s)sequenceDiagram
participant Transaction
participant Committer
participant TiKV
Transaction->>Transaction: mark commit path as prewritten
Transaction->>Committer: commit
Committer->>TiKV: prewrite locks
TiKV-->>Committer: commit failure
Transaction->>Committer: rollback(prewritten=true)
Committer->>TiKV: BatchRollback by start_ts
TiKV-->>Committer: locks cleared
Suggested reviewers: 🚥 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
… 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>
…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>
173895e to
a7bda9e
Compare
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: pingyu The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
[LGTM Timeline notifier]Timeline:
|
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 step, ensuring proper cleanup of any remaining 2PC and pessimistic locks.commit, including retry situations.rollback()succeeds and the client ends with zero remaining locks.