Skip to content

Support bypassing resolved locks for read - #249

Merged
ti-chi-bot[bot] merged 5 commits into
tikv:masterfrom
windtalker:add_try_bypass_lock
Aug 5, 2026
Merged

Support bypassing resolved locks for read#249
ti-chi-bot[bot] merged 5 commits into
tikv:masterfrom
windtalker:add_try_bypass_lock

Conversation

@windtalker

@windtalker windtalker commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

This PR adds a best-effort path for read requests to bypass locks whose transaction status has already been determined, reducing repeated lock handling in read paths.

What is changed and how it works?

  • Add a LockResolver helper to collect transaction IDs that can be bypassed by reads.
  • Schedule committed or rolled-back locks for bounded background resolution instead of always resolving them synchronously on the caller thread.
  • Stop the background resolve worker during Cluster shutdown and avoid continuing to drain swapped pending work after shutdown starts.

Summary by CodeRabbit

  • New Features

    • Added background lock resolution to process eligible locks asynchronously.
    • Read operations can bypass certain locks when safe, reducing unnecessary waiting.
    • Added safeguards to limit queued background lock-resolution work and maintain service responsiveness.
  • Bug Fixes

    • Ensured background lock-resolution tasks stop cleanly during cluster shutdown.
    • Improved handling of lock-resolution errors during asynchronous processing.

@ti-chi-bot ti-chi-bot Bot added dco-signoff: yes Indicates the PR's author has signed the dco. contribution This PR is from a community contributor. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Jul 22, 2026
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@windtalker, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 18 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e84482e0-d045-461b-a5e0-b28db363b1ee

📥 Commits

Reviewing files that changed from the base of the PR and between ea3eedb and a84c53d.

📒 Files selected for processing (1)
  • include/pingcap/kv/Cluster.h
📝 Walkthrough

Walkthrough

LockResolver now supports read-lock bypass decisions and asynchronous cleanup of eligible locks. Cluster starts the resolver worker on its thread pool and stops it during destruction. Pending work is bounded and coordinated with mutex, condition-variable, and atomic state.

Changes

Lock resolution lifecycle

Layer / File(s) Summary
Resolution contracts and state
include/pingcap/kv/Backoff.h, include/pingcap/kv/LockResolver.h
Adds the background-resolution backoff and queue limits, bypass result type, public lifecycle methods, bypass API, parameterized resolution declaration, and synchronization state.
Bypass decisions and background processing
src/kv/LockResolver.cc
Adds bypass evaluation, queues eligible locks for asynchronous cleanup, routes resolution through resolveLocksImpl, updates pushed-lock handling, and processes pending batches in the background worker.
Cluster worker lifecycle
include/pingcap/kv/Cluster.h, src/kv/Cluster.cc
Defines worker counts for mock and regular clusters, schedules backgroundResolve() on the thread pool, and stops the lock resolver during Cluster destruction.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

  • tikv/client-c#244: Extends LockResolver read-path bypass logic for locks outside the caller’s read timestamp.

Suggested reviewers: gengliqi

Sequence Diagram(s)

sequenceDiagram
  participant Cluster
  participant ThreadPool
  participant LockResolver
  participant resolveLocksImpl
  Cluster->>ThreadPool: enqueue backgroundResolve()
  LockResolver->>LockResolver: inspect locks and queue eligible cleanup
  ThreadPool->>LockResolver: run backgroundResolve()
  LockResolver->>resolveLocksImpl: resolve queued lock batches
  Cluster->>LockResolver: stopBgResolve() during destruction
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: supporting read-path bypassing for resolved locks.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
include/pingcap/kv/Cluster.h (1)

65-74: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Consider stopping the background resolver before its dependencies during shutdown.

lock_resolver->stopBgResolve() runs after rpc_client->stop() and region_cache->stop(), but backgroundResolve() depends on both (via resolveLocksImpl/RegionClient). If the worker is mid-batch when the destructor starts, it may keep issuing RPCs/region lookups against already-stopping components until it next observes stopped — caught by backgroundResolve's try/catch, but potentially producing spurious warnings and adding shutdown latency bounded by bgResolveLockMaxBackoff (5s). Moving stopBgResolve() earlier (before rpc_client->stop()/region_cache->stop()) lets the worker exit promptly.

♻️ Suggested reordering
     ~Cluster()
     {
-        rpc_client->stop();
-        mpp_prober->stop();
-        if (region_cache)
-            region_cache->stop();
         if (lock_resolver)
             lock_resolver->stopBgResolve();
+        rpc_client->stop();
+        mpp_prober->stop();
+        if (region_cache)
+            region_cache->stop();
         thread_pool->stop();
     }
🤖 Prompt for 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.

In `@include/pingcap/kv/Cluster.h` around lines 65 - 74, Reorder the Cluster
destructor shutdown sequence so lock_resolver->stopBgResolve() runs before
rpc_client->stop() and region_cache->stop(). Keep the existing conditional
checks and stop the thread_pool afterward, ensuring the background resolver
exits before its RPC and region-cache dependencies are stopped.
🤖 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.

Nitpick comments:
In `@include/pingcap/kv/Cluster.h`:
- Around line 65-74: Reorder the Cluster destructor shutdown sequence so
lock_resolver->stopBgResolve() runs before rpc_client->stop() and
region_cache->stop(). Keep the existing conditional checks and stop the
thread_pool afterward, ensuring the background resolver exits before its RPC and
region-cache dependencies are stopped.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8ea8fd8c-019e-4747-8041-dae48440094b

📥 Commits

Reviewing files that changed from the base of the PR and between 78a557e and 4aa7ef3.

📒 Files selected for processing (5)
  • include/pingcap/kv/Backoff.h
  • include/pingcap/kv/Cluster.h
  • include/pingcap/kv/LockResolver.h
  • src/kv/Cluster.cc
  • src/kv/LockResolver.cc

@ti-chi-bot ti-chi-bot Bot added needs-1-more-lgtm Indicates a PR needs 1 more LGTM. approved labels Jul 24, 2026
Comment thread src/kv/Cluster.cc
if (lock_resolver)
{
thread_pool->enqueue([this] {
lock_resolver->backgroundResolve();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Reserve a worker for background lock resolution

I’m Codex reviewer. The production Cluster(pd_addrs, config) constructor creates only three pool workers, but startBackgroundTasks() now enqueues four non-returning loops in order: RPC maintenance, MPP probing, region-cache updates, and this resolver. The first three therefore occupy every worker until shutdown, leaving backgroundResolve() queued forever. As a result, the bounded pending-lock queue is never drained, eventually reaches its 4096-lock limit, and foreground reads fall back to synchronous lock resolution. Please increase the pool size or give the resolver a dedicated worker, and ideally add a liveness test that verifies pending locks are actually consumed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. You are right that this can starve backgroundResolve(): the production Cluster had 3 FixedThreadPool workers but now schedules 4 long-running loops, so the resolver task could remain queued forever. I fixed this in ea3eedb by making the worker count match the number of non-returning background tasks. Production Cluster now reserves 4 workers, and the mock/test Cluster now also initializes oracle +
lock_resolver and reserves 3 workers. I also moved stopBgResolve() before stopping RPC/RegionCache so shutdown order matches the resolver dependencies.

Signed-off-by: xufei <xufeixw@mail.ustc.edu.cn>
Signed-off-by: xufei <xufeixw@mail.ustc.edu.cn>
Signed-off-by: xufei <xufeixw@mail.ustc.edu.cn>
Signed-off-by: xufei <xufeixw@mail.ustc.edu.cn>
@windtalker
windtalker force-pushed the add_try_bypass_lock branch from 584b1ff to ea3eedb Compare August 4, 2026 08:07
@ti-chi-bot ti-chi-bot Bot added dco-signoff: no Indicates the PR's author has not signed dco. and removed dco-signoff: yes Indicates the PR's author has signed the dco. labels Aug 4, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
include/pingcap/kv/Cluster.h (1)

71-77: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Background lock resolution is not synchronized with cluster shutdown. stopBgResolve only sets a flag, and the worker is joined later by thread_pool->stop(). Between those two points the destructor stops rpc_client and region_cache, so an in-flight resolveLocksImpl can issue requests against stopped subsystems. The stop flag is also not observed inside a long Backoffer(bgResolveLockMaxBackoff) sleep.

  • include/pingcap/kv/Cluster.h#L71-L77: call lock_resolver->stopBgResolve() and then thread_pool->stop() before rpc_client->stop(), mpp_prober->stop(), and region_cache->stop(), so the worker is joined before its dependencies stop.
  • src/kv/LockResolver.cc#L632-L656: make the worker exit promptly after stopped is set, for example by checking stopped inside the per-batch loop before each RPC and by bounding the background backoff, so the join in thread_pool->stop() does not wait for a full backoff cycle.
🤖 Prompt for 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.

In `@include/pingcap/kv/Cluster.h` around lines 71 - 77, Synchronize lock-resolver
shutdown before stopping its dependencies: in include/pingcap/kv/Cluster.h lines
71-77, call stopBgResolve and then thread_pool->stop before stopping rpc_client,
mpp_prober, or region_cache. In src/kv/LockResolver.cc lines 632-656, update the
background worker loop to check stopped before each RPC and bound or interrupt
the Backoffer(bgResolveLockMaxBackoff) wait so joining exits promptly.
🧹 Nitpick comments (1)
src/kv/LockResolver.cc (1)

148-156: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Consider enqueuing one batch per transaction instead of one per lock.

Each bypassed lock creates a separate queue entry through addPendingLocksForBgResolve(caller_start_ts, {lock}). A scan that hits many locks of the same transaction therefore consumes many queue slots against maxPendingLocksForBgResolve, and the worker resolves each entry with its own Backoffer. This repeats getTxnStatusFromLock and ResolveLock requests for the same txn_id.

Collecting bypassed locks in a local per-txn_id vector and enqueuing once after the loop would reduce both queue pressure and RPC volume.

🤖 Prompt for 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.

In `@src/kv/LockResolver.cc` around lines 148 - 156, Update the lock-scan flow
around addPendingLocksForBgResolve to collect bypassed locks grouped by txn_id
in local vectors, then enqueue one batch per transaction after the scan instead
of enqueueing each lock immediately. Preserve pushed tracking and synchronous
fallback when background enqueueing fails, while ensuring background resolution
does not enqueue again.
🤖 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.

Outside diff comments:
In `@include/pingcap/kv/Cluster.h`:
- Around line 71-77: Synchronize lock-resolver shutdown before stopping its
dependencies: in include/pingcap/kv/Cluster.h lines 71-77, call stopBgResolve
and then thread_pool->stop before stopping rpc_client, mpp_prober, or
region_cache. In src/kv/LockResolver.cc lines 632-656, update the background
worker loop to check stopped before each RPC and bound or interrupt the
Backoffer(bgResolveLockMaxBackoff) wait so joining exits promptly.

---

Nitpick comments:
In `@src/kv/LockResolver.cc`:
- Around line 148-156: Update the lock-scan flow around
addPendingLocksForBgResolve to collect bypassed locks grouped by txn_id in local
vectors, then enqueue one batch per transaction after the scan instead of
enqueueing each lock immediately. Preserve pushed tracking and synchronous
fallback when background enqueueing fails, while ensuring background resolution
does not enqueue again.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: eafd08f8-53a7-4b15-8481-3cfd92ad7ad5

📥 Commits

Reviewing files that changed from the base of the PR and between 4aa7ef3 and ea3eedb.

📒 Files selected for processing (5)
  • include/pingcap/kv/Backoff.h
  • include/pingcap/kv/Cluster.h
  • include/pingcap/kv/LockResolver.h
  • src/kv/Cluster.cc
  • src/kv/LockResolver.cc
🚧 Files skipped from review as they are similar to previous changes (3)
  • include/pingcap/kv/Backoff.h
  • src/kv/Cluster.cc
  • include/pingcap/kv/LockResolver.h

Signed-off-by: xufei <xufeixw@mail.ustc.edu.cn>
@windtalker
windtalker force-pushed the add_try_bypass_lock branch from ea3eedb to a84c53d Compare August 4, 2026 08:48
@ti-chi-bot ti-chi-bot Bot added dco-signoff: yes Indicates the PR's author has signed the dco. and removed dco-signoff: no Indicates the PR's author has not signed dco. labels Aug 4, 2026
@ti-chi-bot ti-chi-bot Bot added the lgtm label Aug 5, 2026
@ti-chi-bot

ti-chi-bot Bot commented Aug 5, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: ekexium, gengliqi

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@ti-chi-bot ti-chi-bot Bot removed the needs-1-more-lgtm Indicates a PR needs 1 more LGTM. label Aug 5, 2026
@ti-chi-bot

ti-chi-bot Bot commented Aug 5, 2026

Copy link
Copy Markdown

[LGTM Timeline notifier]

Timeline:

  • 2026-07-24 10:02:32.873786111 +0000 UTC m=+1571938.909881167: ☑️ agreed by gengliqi.
  • 2026-08-05 05:28:15.012089976 +0000 UTC m=+2592281.048185042: ☑️ agreed by ekexium.

@ti-chi-bot
ti-chi-bot Bot merged commit 55aede2 into tikv:master Aug 5, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved contribution This PR is from a community contributor. dco-signoff: yes Indicates the PR's author has signed the dco. lgtm size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants