Skip to content

*: add tidb_paging_size_bytes and forward it to coprocessor RPC#68091

Merged
ti-chi-bot[bot] merged 6 commits into
pingcap:masterfrom
JmPotato:paging-size-bytes
Jul 1, 2026
Merged

*: add tidb_paging_size_bytes and forward it to coprocessor RPC#68091
ti-chi-bot[bot] merged 6 commits into
pingcap:masterfrom
JmPotato:paging-size-bytes

Conversation

@JmPotato

@JmPotato JmPotato commented Apr 28, 2026

Copy link
Copy Markdown
Member

What problem does this PR solve?

Issue Number: close #68090

Problem Summary:

Today TiDB's coprocessor paging protocol breaks pages only on row count (paging_size). For Resource Control workloads, RU pre-charge in PD's resource controller would benefit from an additional, byte-granular page-break signal so that a single page's response volume is bounded by bytes rather than only by rows.

pingcap/kvproto#1448 adds a new paging_size_bytes field (tag 17) on coprocessor.Request. This PR adds the TiDB-side knob and plumbing so the byte budget can be set per session and forwarded onto each coprocessor RPC.

What changed and how does it work?

  • New tidb_paging_size_bytes global+session sysvar (default 0, disabled). Allowed inside SET_VAR hints.
  • session.GetDistSQLCtx resolves the effective byte budget once: it keeps the session value only when Resource Control is enabled and the statement resource group has a non-negative adjusted burst limit; otherwise it forwards 0.
  • The effective value flows through DistSQLContext.PagingSizeBytes into kv.Request.Paging.PagingSizeBytes via RequestBuilder; no extra RC state is carried in kv.Request.
  • In pkg/store/copr:
    • Byte-budget paging is applied only to TiKV DAG requests; BuildCopIterator zeroes the budget for any other request (non-TiKV or non-DAG), mirroring how Paging.Enable is handled, so kv.Request.Paging.PagingSizeBytes stays the single source of truth.
    • paging_size_bytes is propagated independently from row-count paging_size; it does not force-enable or rewrite row-count paging settings, and it survives row-count small-limit downgrades.
    • Downstream reads (the outgoing coprocessor.Request.PagingSizeBytes, retries, and region splits) take the budget straight off the request instead of a per-task copy, so no retry/split path can drop it. Index-lookup push down clears the budget alongside Paging.Enable/Cacheable.
    • Batch copr is disabled for byte-budget paging because paged child tasks need range-resume semantics.
    • The cop cache key uses a single paging marker byte for both row-count and byte-budget paging: a cached page is self-describing via its returned range, so the exact paging_size/paging_size_bytes values never affect cache correctness, and paging vs non-paging requests stay in separate key spaces (no collision).
    • Paging-specific failpoints, sorted-range checks, cache-hit range restoration, and KeepOrder response buffering treat byte-budget paging as the same paging protocol surface while keeping its budget independent from row-count paging.

Check List

Tests

  • Unit test
  • Integration test

Validated locally:

  • ./tools/check/failpoint-go-test.sh pkg/session -run TestDistSQLCtxPagingSizeBytesRequiresHardCappedResourceGroup -count=1
  • ./tools/check/failpoint-go-test.sh pkg/distsql -run TestRequestBuilderKeepsPagingSizeBytesWhenPagingDisabled -count=1
  • ./tools/check/failpoint-go-test.sh pkg/store/copr -run 'Test(BuildCacheKey|GetSet|BuildCopTasksWithPagingSizeBytes)$' -count=1
  • ./tools/check/failpoint-go-test.sh pkg/store/copr/copr_test -run TestBuildCopIteratorWithBatchStoreCopr -count=1
  • (cd tests/integrationtest && ./run-tests.sh -r sessionctx/setvar)
  • make lint
  • git diff --check

Documentation

  • Affects user behaviors
  • Contains syntax changes
  • Contains variable changes
  • Contains experimental features
  • Changes MySQL compatibility

Related PRs

Release note

None

Summary by CodeRabbit

  • New Features

    • Added a new session and system variable for byte-based paging limits.
    • Paging-related requests now carry effective byte budget settings.
    • TiKV coprocessor paging can now use a byte budget in addition to row-count limits.
  • Bug Fixes

    • Preserved paging byte-budget settings when paging is disabled in some request flows.
    • Updated paging behavior to better handle small result limits and retry scenarios.

@ti-chi-bot ti-chi-bot Bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Apr 28, 2026
@coderabbitai

coderabbitai Bot commented Apr 28, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR refreshes the kvproto dependency pin and adds paging-byte coverage in DistSQL and coprocessor tests, with Bazel shard count updates for both test suites.

Changes

kvproto pin refresh

Layer / File(s) Summary
Pinned kvproto refresh
go.mod, DEPS.bzl
The kvproto requirement and Bazel pin are updated together for the newer revision.

Paging byte-budget coverage

Layer / File(s) Summary
RequestBuilder paging fields
pkg/distsql/request_builder_test.go, pkg/distsql/BUILD.bazel
A RequestBuilder test covers PagingSizeBytes and RCNonBurstable, and distsql_test shard count changes from 33 to 34.
Coprocessor paging-byte cases
pkg/store/copr/copr_test/coprocessor_test.go, pkg/store/copr/BUILD.bazel
The coprocessor batch-store test adds PagingSizeBytes and RCNonBurstable, adds a byte-budget paging case, and copr_test shard count changes from 43 to 45.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

approved, lgtm

Suggested reviewers

  • gengliqi
  • windtalker
  • 0xPoe

Poem

\o/
I hopped where bytes and pages meet,
The new pin squeaked on rabbit feet.
Tests thumped twice, then all was bright,
A byte-sized moon hopped into sight. 🐇

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning BUILD.bazel shard_count changes in pkg/distsql and pkg/store/copr are unrelated to the issue and look like extra test-infra changes. Move the Bazel shard-count adjustments to a separate PR, or explain why they are required for this feature in the issue or description.
Docstring Coverage ⚠️ Warning Docstring coverage is 8.70% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and matches the main change: adding tidb_paging_size_bytes and forwarding it to coprocessor RPCs.
Linked Issues check ✅ Passed The changes implement the sysvar, SET_VAR support, DistSQL and coprocessor plumbing, retry preservation, and small-limit clearing required by #68090.
Description check ✅ Passed The PR description follows the required template and includes the issue link, problem summary, change summary, tests, documentation, and release note.
✨ Finishing Touches
🧪 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.

@ti-chi-bot ti-chi-bot Bot added release-note-none Denotes a PR that doesn't merit a release note. and removed release-note Denotes a PR that will be considered when it comes time to generate release notes. labels Apr 28, 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.

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
pkg/store/copr/coprocessor.go (1)

124-151: ⚠️ Potential issue | 🟡 Minor

Keep DisablePaging from being bypassed by byte-budget paging.

Line 124 only turns off req.Paging.Enable, but Lines 144-150 can immediately turn paging back on when PagingSizeBytes > 0. That makes the failpoint stop disabling paging for the new path, which can break failpoint-based tests and debugging.

Proposed fix
 failpoint.Inject("DisablePaging", func(_ failpoint.Value) {
 	req.Paging.Enable = false
+	req.Paging.PagingSizeBytes = 0
 })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/store/copr/coprocessor.go` around lines 124 - 151, The DisablePaging
failpoint only clears req.Paging.Enable, but later byte-budget logic
(pagingBytesEligible + req.Paging.PagingSizeBytes > 0) can re-enable paging;
update the failpoint handler to also clear the byte-budget signal by setting
req.Paging.PagingSizeBytes = 0 (and keep req.Paging.Enable = false) so the later
block cannot force paging back on; locate the failpoint.Inject("DisablePaging",
...) and modify its closure to zero out req.Paging.PagingSizeBytes (and
optionally other paging fields you want forced off) to ensure the failpoint
fully disables paging.
🧹 Nitpick comments (1)
go.mod (1)

370-373: Consider adding explicit cleanup tracking for the temporary kvproto fork pin.

This temporary replace is appropriate while PR pingcap/kvproto#1448 remains unmerged. However, tying the cleanup to a concrete tracker (issue link or internal checklist) would improve maintainability and prevent long-term drift on the personal fork.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@go.mod` around lines 370 - 373, The temporary go.mod replace pin for
github.com/pingcap/kvproto => github.com/JmPotato/kvproto
v0.0.0-20260428063603-042bfc75f2ac needs explicit cleanup tracking: add a short
TODO comment next to that replace line referencing a concrete tracker (create a
public issue or internal checklist ID and paste the URL/ID) and include the
upstream PR number (pingcap/kvproto#1448) and a deadline or review date;
alternatively create the issue now and update the go.mod comment to point to
that issue so reviewers can find and remove the fork pin when the upstream PR is
merged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/sessionctx/variable/sysvar.go`:
- Around line 2985-2988: The new sysvar registration for TiDBPagingSizeBytes
omits the SET_VAR hint eligibility flag; update the var entry for Name:
vardef.TiDBPagingSizeBytes to include IsHintUpdatableVerified: true alongside
the existing Scope/Name/Value/Type/MinValue/MaxValue/SetSession fields so the
variable is explicitly marked eligible for SET_VAR hint handling (keep the
current SetSession closure as-is).

---

Outside diff comments:
In `@pkg/store/copr/coprocessor.go`:
- Around line 124-151: The DisablePaging failpoint only clears
req.Paging.Enable, but later byte-budget logic (pagingBytesEligible +
req.Paging.PagingSizeBytes > 0) can re-enable paging; update the failpoint
handler to also clear the byte-budget signal by setting
req.Paging.PagingSizeBytes = 0 (and keep req.Paging.Enable = false) so the later
block cannot force paging back on; locate the failpoint.Inject("DisablePaging",
...) and modify its closure to zero out req.Paging.PagingSizeBytes (and
optionally other paging fields you want forced off) to ensure the failpoint
fully disables paging.

---

Nitpick comments:
In `@go.mod`:
- Around line 370-373: The temporary go.mod replace pin for
github.com/pingcap/kvproto => github.com/JmPotato/kvproto
v0.0.0-20260428063603-042bfc75f2ac needs explicit cleanup tracking: add a short
TODO comment next to that replace line referencing a concrete tracker (create a
public issue or internal checklist ID and paste the URL/ID) and include the
upstream PR number (pingcap/kvproto#1448) and a deadline or review date;
alternatively create the issue now and update the go.mod comment to point to
that issue so reviewers can find and remove the fork pin when the upstream PR is
merged.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 82e5a82a-02bd-465b-826d-ac92d5da7b83

📥 Commits

Reviewing files that changed from the base of the PR and between 7940e68 and 7f2f377.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (17)
  • DEPS.bzl
  • go.mod
  • pkg/distsql/context/context.go
  • pkg/distsql/context/context_test.go
  • pkg/distsql/request_builder.go
  • pkg/kv/kv.go
  • pkg/session/session.go
  • pkg/sessionctx/vardef/tidb_vars.go
  • pkg/sessionctx/variable/session.go
  • pkg/sessionctx/variable/setvar_affect.go
  • pkg/sessionctx/variable/sysvar.go
  • pkg/store/copr/BUILD.bazel
  • pkg/store/copr/copr_test/coprocessor_test.go
  • pkg/store/copr/coprocessor.go
  • pkg/store/copr/coprocessor_test.go
  • tests/integrationtest/r/sessionctx/setvar.result
  • tests/integrationtest/t/sessionctx/setvar.test

Comment on lines +2985 to +2988
{Scope: vardef.ScopeGlobal | vardef.ScopeSession, Name: vardef.TiDBPagingSizeBytes, Value: strconv.Itoa(vardef.DefPagingSizeBytes), Type: vardef.TypeUnsigned, MinValue: 0, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error {
s.PagingSizeBytes = int(TidbOptInt64(val, int64(vardef.DefPagingSizeBytes)))
return nil
}},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add explicit SET_VAR-hint eligibility metadata for tidb_paging_size_bytes.

Line 2985 registers the new sysvar but omits IsHintUpdatableVerified: true. Since this variable is intended to be used in SET_VAR(...), please mark it explicitly to avoid hint gating mismatches.

🔧 Proposed fix
-{Scope: vardef.ScopeGlobal | vardef.ScopeSession, Name: vardef.TiDBPagingSizeBytes, Value: strconv.Itoa(vardef.DefPagingSizeBytes), Type: vardef.TypeUnsigned, MinValue: 0, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error {
+{Scope: vardef.ScopeGlobal | vardef.ScopeSession, Name: vardef.TiDBPagingSizeBytes, Value: strconv.Itoa(vardef.DefPagingSizeBytes), Type: vardef.TypeUnsigned, MinValue: 0, MaxValue: math.MaxInt64, IsHintUpdatableVerified: true, SetSession: func(s *SessionVars, val string) error {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{Scope: vardef.ScopeGlobal | vardef.ScopeSession, Name: vardef.TiDBPagingSizeBytes, Value: strconv.Itoa(vardef.DefPagingSizeBytes), Type: vardef.TypeUnsigned, MinValue: 0, MaxValue: math.MaxInt64, SetSession: func(s *SessionVars, val string) error {
s.PagingSizeBytes = int(TidbOptInt64(val, int64(vardef.DefPagingSizeBytes)))
return nil
}},
{Scope: vardef.ScopeGlobal | vardef.ScopeSession, Name: vardef.TiDBPagingSizeBytes, Value: strconv.Itoa(vardef.DefPagingSizeBytes), Type: vardef.TypeUnsigned, MinValue: 0, MaxValue: math.MaxInt64, IsHintUpdatableVerified: true, SetSession: func(s *SessionVars, val string) error {
s.PagingSizeBytes = int(TidbOptInt64(val, int64(vardef.DefPagingSizeBytes)))
return nil
}},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/sessionctx/variable/sysvar.go` around lines 2985 - 2988, The new sysvar
registration for TiDBPagingSizeBytes omits the SET_VAR hint eligibility flag;
update the var entry for Name: vardef.TiDBPagingSizeBytes to include
IsHintUpdatableVerified: true alongside the existing
Scope/Name/Value/Type/MinValue/MaxValue/SetSession fields so the variable is
explicitly marked eligible for SET_VAR hint handling (keep the current
SetSession closure as-is).

@tiprow

tiprow Bot commented Apr 28, 2026

Copy link
Copy Markdown

@JmPotato: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
fast_test_tiprow 48efbe7 link true /test fast_test_tiprow

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@codecov

codecov Bot commented Apr 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 78.57143% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.4628%. Comparing base (693e52c) to head (78c69d1).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@               Coverage Diff                @@
##             master     #68091        +/-   ##
================================================
- Coverage   76.3268%   74.4628%   -1.8641%     
================================================
  Files          2041       2045         +4     
  Lines        561003     573862     +12859     
================================================
- Hits         428196     427314       -882     
- Misses       131906     146359     +14453     
+ Partials        901        189       -712     
Flag Coverage Δ
integration 41.0771% <78.5714%> (+1.4490%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
dumpling 60.4471% <ø> (ø)
parser ∅ <ø> (∅)
br 47.6078% <ø> (-15.1433%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread pkg/store/copr/coprocessor.go Outdated
if pagingBytesEligible(req) && req.Paging.PagingSizeBytes > 0 {
if !req.Paging.Enable {
req.Paging.Enable = true
req.Paging.MinPagingSize = paging.MinPagingSize

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

PagingSizeBytes already bounds each page, so the geometric ramp-up serves no purpose here. Since the user set tidb_enable_paging = OFF, so we shouldn't reintroduce what they disabled. Suggest setting it to the same value as MaxPagingSize.

Comment thread pkg/store/copr/coprocessor.go Outdated
// The TiKV coprocessor protocol requires paging to be enabled for the
// PagingSizeBytes field to take effect. When force-enabling paging, we
// use minimal row-count parameters so the byte budget becomes the
// dominant page-break signal.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

To make the byte budget dominant, Min/MaxPagingSize must be large (so row-count cap doesn't fire first), not minimal.

With this being said, we might want to set Min/MaxPagingSize (line 147/148) to larger values. The math here is: For a 4 MiB byte budget, current MaxPagingSize setup means the byte budget only dominates when row_width ≥ 84 B.

@JmPotato JmPotato force-pushed the paging-size-bytes branch from 48efbe7 to 852f963 Compare June 26, 2026 07:15
@ti-chi-bot ti-chi-bot Bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Jun 26, 2026
@JmPotato JmPotato force-pushed the paging-size-bytes branch from 852f963 to 97de07a Compare June 26, 2026 08:08
@ti-chi-bot ti-chi-bot Bot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Jun 26, 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.

🧹 Nitpick comments (2)
cmd/mirror/BUILD.bazel (1)

36-43: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Drop flaky = True unless this target is known to be nondeterministic.

These tests only exercise local parsing/helpers, so marking the target flaky will mask real regressions and add noisy reruns in CI. As per coding guidelines, "Test files: Prefer extending existing test suites and fixtures over creating new scaffolding; keep test changes minimal and deterministic."

Suggested change
 go_test(
     name = "mirror_test",
     timeout = "short",
     srcs = ["skylarkutil_test.go"],
     embed = [":mirror_lib"],
-    flaky = True,
     shard_count = 2,
 )
🤖 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 `@cmd/mirror/BUILD.bazel` around lines 36 - 43, Remove the flaky setting from
the mirror_test go_test target in BUILD.bazel unless there is a proven
nondeterminism issue; keep the test definition for mirror_test deterministic and
minimal by deleting the flaky attribute and leaving the rest of the target
unchanged.

Source: Coding guidelines

cmd/mirror/mirror.go (1)

397-400: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Wrap proxy-URL formatting failures with module coordinates.

A bare return err here makes it hard to tell which dependency broke generation. Include replaced.Path and replaced.Version in the error so failures are actionable. As per coding guidelines, "Go code: Keep error handling actionable and contextual; avoid silently swallowing errors."

Suggested change
 		goProxyURL, err := formatGoProxyURL(replaced.Path, replaced.Version)
 		if err != nil {
-			return err
+			return fmt.Errorf("format go proxy url for %s@%s: %w", replaced.Path, replaced.Version, err)
 		}
🤖 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 `@cmd/mirror/mirror.go` around lines 397 - 400, The error returned from
formatGoProxyURL in mirror.go is too bare and loses module context. Update the
error handling in the proxy URL generation flow to wrap the returned error with
the module coordinates from replaced.Path and replaced.Version so the failing
dependency is identifiable. Use the existing variables in this block around
formatGoProxyURL to add actionable context before returning the error.

Source: Coding guidelines

🤖 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 `@cmd/mirror/BUILD.bazel`:
- Around line 36-43: Remove the flaky setting from the mirror_test go_test
target in BUILD.bazel unless there is a proven nondeterminism issue; keep the
test definition for mirror_test deterministic and minimal by deleting the flaky
attribute and leaving the rest of the target unchanged.

In `@cmd/mirror/mirror.go`:
- Around line 397-400: The error returned from formatGoProxyURL in mirror.go is
too bare and loses module context. Update the error handling in the proxy URL
generation flow to wrap the returned error with the module coordinates from
replaced.Path and replaced.Version so the failing dependency is identifiable.
Use the existing variables in this block around formatGoProxyURL to add
actionable context before returning the error.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d473fd72-4dec-42c6-b15d-4bad646032b9

📥 Commits

Reviewing files that changed from the base of the PR and between 852f963 and 97de07a.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (10)
  • DEPS.bzl
  • cmd/mirror/BUILD.bazel
  • cmd/mirror/mirror.go
  • cmd/mirror/skylarkutil.go
  • cmd/mirror/skylarkutil_test.go
  • go.mod
  • pkg/distsql/BUILD.bazel
  • pkg/distsql/request_builder_test.go
  • pkg/store/copr/BUILD.bazel
  • pkg/store/copr/copr_test/coprocessor_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • go.mod
  • DEPS.bzl

@JmPotato JmPotato force-pushed the paging-size-bytes branch 3 times, most recently from 1d8aa66 to 7bffdb2 Compare June 26, 2026 09:36
@ti-chi-bot ti-chi-bot Bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Jun 26, 2026
@JmPotato JmPotato force-pushed the paging-size-bytes branch 3 times, most recently from a349ee6 to 358f697 Compare June 29, 2026 08:33
Comment thread pkg/store/copr/coprocessor.go Outdated
req.Paging.Enable = false
}
var pagingSizeBytes uint64
if req.StoreType == kv.TiKV && req.Tp == kv.ReqTypeDAG && req.Paging.PagingSizeBytes > 0 {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The DisablePaging failpoint above can still send byte-budget paging because this preserves PagingSizeBytes. Please clear PagingSizeBytes in the failpoint too.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done — the DisablePaging failpoint now clears PagingSizeBytes alongside Enable:

failpoint.Inject("DisablePaging", func(_ failpoint.Value) {
    req.Paging.Enable = false
    req.Paging.PagingSizeBytes = 0
})

As extra hardening, BuildCopIterator now also zeroes req.Paging.PagingSizeBytes for any non-TiKV / non-DAG request, mirroring how Paging.Enable is handled. So req.Paging.PagingSizeBytes is the single source of truth and the byte budget can no longer slip past the gate from any path.

@JmPotato JmPotato force-pushed the paging-size-bytes branch from 358f697 to 104d606 Compare June 29, 2026 08:41
@ti-chi-bot ti-chi-bot Bot removed the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Jun 29, 2026
@ti-chi-bot ti-chi-bot Bot added the size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. label Jun 29, 2026
@JmPotato JmPotato force-pushed the paging-size-bytes branch from 104d606 to aaa0d75 Compare June 29, 2026 08:56
builder.SetPaging(dctx.EnablePaging)
builder.Request.Paging.MinPagingSize = uint64(dctx.MinPagingSize)
builder.Request.Paging.MaxPagingSize = uint64(dctx.MaxPagingSize)
builder.Request.Paging.PagingSizeBytes = uint64(dctx.PagingSizeBytes)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Non-blocking: byte-only paging has Enable == false, so downstream selectResult.paging will still be false and DistSQLQueryHistogram labels it as common. Could we include PagingSizeBytes > 0 there too?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch — done. selectResult.paging now includes the byte budget, so byte-only paging is recorded as paging (not common) in DistSQLQueryHistogram:

paging: kvReq.Paging.Enable || kvReq.Paging.PagingSizeBytes > 0,

That field is observability-only (its only use is the histogram label), so this is purely a metrics-accuracy fix with no execution impact.

@rleungx rleungx left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The rest LGTM

@ti-chi-bot ti-chi-bot Bot added the needs-1-more-lgtm Indicates a PR needs 1 more LGTM. label Jun 29, 2026
@JmPotato JmPotato force-pushed the paging-size-bytes branch 2 times, most recently from b1d701a to 2374ae7 Compare June 29, 2026 11:05
// in paging request, a request will be returned in multi batches,
// enlarge the channel size to avoid the request blocked by buffer full.
if req.Paging.Enable {
if req.Paging.Enable || req.Paging.PagingSizeBytes > 0 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The PagingSizeBytes would enable coprocessor paging execution even the Paging is disabled, not sure if it is a possible risk.
Previously, there would be performance regression in some cases when paging is used.

@JmPotato JmPotato Jul 1, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is by-design behavior.

The req.Paging.Enable switch was used only to control whether paging_size was enabled. However, paging_size_bytes follows a completely different logic path. Although the names are similar, paging_size_bytes is controlled exclusively by RU-based Resource Control.

In the current implementation, beyond gating the Resource Control feature itself, we will introduce even stricter logic. Specifically, paging_size_bytes will only be enabled when Resource Group is active and there is significant throttling or a clear shortage of tokens.

The goal is to achieve more granular control rather than enabling it across all scenarios. Therefore, we chose not to couple it with the req.Paging.Enable switch and instead use a relatively independent logic.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Got it, better keeping an eye on the performance regression tests.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We will conduct dedicated regression testing to ensure that enabling paging_size_bytes does not impact the performance of normal workloads.

@ti-chi-bot ti-chi-bot Bot added lgtm and removed needs-1-more-lgtm Indicates a PR needs 1 more LGTM. labels Jul 1, 2026
@ti-chi-bot

ti-chi-bot Bot commented Jul 1, 2026

Copy link
Copy Markdown

[LGTM Timeline notifier]

Timeline:

  • 2026-06-29 10:12:29.721910281 +0000 UTC m=+34291.422289704: ☑️ agreed by rleungx.
  • 2026-07-01 02:50:29.595008814 +0000 UTC m=+180571.295388227: ☑️ agreed by cfzjywxk.

JmPotato added 6 commits July 1, 2026 11:09
Add a TiDB-side knob `tidb_paging_size_bytes` (global+session sysvar,
default 0) and plumb the value end-to-end so it lands as the new
`paging_size_bytes` field on `coprocessor.Request`.

- `tidb_paging_size_bytes` is allowed in `SET_VAR` hints; default 0
  disables byte-budget paging.
- The value flows through `DistSQLContext` into
  `kv.Request.Paging.PagingSizeBytes` via `RequestBuilder`.
- In the cop client, `pagingBytesEligible` gates the feature to
  TiKV + DAG requests. When the byte budget is positive on an
  eligible request whose row-count paging is disabled, paging is
  force-enabled with minimum row parameters so the byte budget
  becomes the dominant page-break signal. This must happen before
  `checkStoreBatchCopr` because batch copr is incompatible with
  paging.
- The byte budget is carried on each generated `copTask`,
  populates `coprocessor.Request.PagingSizeBytes` on outgoing
  RPCs, propagates onto retried tasks (region/lock errors), and
  is cleared together with `pagingSize` when the small-limit
  downgrade fires.

Dependency:

- Pin `pingcap/kvproto` to JmPotato/kvproto demo/ru-paging-size
  which adds `paging_size_bytes` (tag 17) to `coprocessor.Request`
  via pingcap/kvproto#1448; revert this replace once that PR is
  merged and tagged.

Tests:

- `TestPagingBytesEligible` covers eligibility for TiKV/DAG vs
  TiFlash and non-DAG requests.
- `TestBuildCopTasksWithPagingSizeBytes` covers task construction
  with and without small-limit downgrade.
- `tests/integrationtest/sessionctx/setvar` is extended to cover
  the new sysvar (default, set, set via SET_VAR hint).

Signed-off-by: JmPotato <github@ipotato.me>
Byte-budget paging only delivers RU-control value for resource groups
that are hard-capped at RU_PER_SEC. For burstable or unlimited groups,
or when Resource Control is disabled, the per-page byte break adds
RPC overhead without bounding any token budget.

Add an `RCNonBurstable` bit to `kv.Request.Paging` and propagate it
through `DistSQLContext`. The bit is computed once per
`DistSQLContext` in `session.GetDistSQLCtx` from the current
statement's resource group: it is true iff `EnableResourceControl` is
on and `InfoSchema.ResourceGroupByName(...)` returns a group whose
`GetBurstLimitAdjusted()` is non-negative.

The default group is treated as a normal group: by default its
`BurstLimit` is -1 so byte-budget paging stays off, but if the user
alters its config to a non-negative `BurstLimit` it will trigger like
any other RC-capped group.

`pagingBytesEligible` now requires `req.Paging.RCNonBurstable` in
addition to TiKV + DAG, so the byte budget is only set on RPCs that
will benefit from it.

Signed-off-by: JmPotato <github@ipotato.me>
Signed-off-by: JmPotato <github@ipotato.me>
Signed-off-by: JmPotato <github@ipotato.me>
Signed-off-by: JmPotato <github@ipotato.me>
Drop the redundant per-task copTask.pagingSizeBytes and the
buildCopTaskOpt field, and read req.Paging.PagingSizeBytes directly,
mirroring how Paging.Enable is gated. BuildCopIterator now zeroes the
byte budget for non-TiKV/non-DAG requests, which also removes a stray
budget that could spuriously disable store-batch copr on TiFlash or
non-DAG requests. New retry/split paths can no longer drop the budget.

Simplify the cop cache key back to a single paging marker byte: a cached
page is self-describing via its returned range, so the exact PagingSize
/ PagingSizeBytes values never affect cache correctness. This reverts
the unnecessary 8-byte encodings and removes the latent PagingSize=N vs
PagingSizeBytes=N key collision.

Clear Paging.PagingSizeBytes in index-lookup push down, matching the
existing Paging.Enable/Cacheable handling.

Signed-off-by: JmPotato <github@ipotato.me>
@JmPotato JmPotato force-pushed the paging-size-bytes branch from 2374ae7 to 78c69d1 Compare July 1, 2026 03:09

@yudongusa yudongusa 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.

Please open a document PR to state this is an internal use variable

@ti-chi-bot

ti-chi-bot Bot commented Jul 1, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: cfzjywxk, rleungx, yudongusa

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 added the approved label Jul 1, 2026
@JmPotato

JmPotato commented Jul 1, 2026

Copy link
Copy Markdown
Member Author

/retest

@ti-chi-bot ti-chi-bot Bot merged commit 4ccb1ae into pingcap:master Jul 1, 2026
34 checks passed
@JmPotato JmPotato deleted the paging-size-bytes branch July 1, 2026 05:22
@ti-chi-bot

ti-chi-bot Bot commented Jul 1, 2026

Copy link
Copy Markdown

@JmPotato: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
idc-jenkins-ci-tidb/check_dev_2 78c69d1 link unknown /test check-dev2

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved lgtm release-note-none Denotes a PR that doesn't merit a release note. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

store/copr: forward tidb_paging_size_bytes byte budget to TiKV coprocessor RPC

5 participants