Skip to content

pkg/ddl, pkg/dxf: add local sort disk check and logging for backfill workers#68320

Open
expxiaoli wants to merge 5 commits into
pingcap:masterfrom
expxiaoli:fix_68293
Open

pkg/ddl, pkg/dxf: add local sort disk check and logging for backfill workers#68320
expxiaoli wants to merge 5 commits into
pingcap:masterfrom
expxiaoli:fix_68293

Conversation

@expxiaoli

@expxiaoli expxiaoli commented May 12, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: close #68293

Problem Summary:

When add index runs with local sort on TiDB workers, we do not have a worker-side admission check for local disk headroom. A new backfill task may start even when the remaining disk is not enough for the ongoing local-sort workload plus the extra 10% headroom reserved for partial import.

Besides, we do not have a summary view of how much local disk space the backfill actually used. This makes it harder to diagnose disk pressure and compare the observed usage with the expected local-sort disk requirement.

What changed and how does it work?

This PR improves both prevention and observability for local-sort add index backfill.

The change:

  • adds local-sort disk usage sampling to the read-index backfill pipeline and logs a structured summary after the pipeline finishes
  • adds a TiDB worker-side disk precheck when the worker receives a local-sort backfill task
  • snapshots current executor tasks from the DXF slot manager and derives the required slots for each local-sort job
  • calculates the required disk bytes with the following model:
    • required_bytes = required_slots * 512MB for each job
    • all_jobs_required_bytes = sum(required_bytes) for all running jobs plus the new job
    • all_jobs_used_bytes = sum(used_bytes) for running jobs
    • all_jobs_gap_bytes = max(all_jobs_required_bytes - all_jobs_used_bytes, 0)
    • total_required_bytes = total_capacity * 10% + all_jobs_gap_bytes
  • returns an error early when the available disk space is not greater than total_required_bytes, so add index local sort can fail fast before entering a higher-risk execution path
  • exposes the minimal task-slot snapshot and tracked disk-usage helpers needed by the DDL worker, and adds regression tests for the new check

This keeps the local-sort algorithm unchanged, but makes the worker more defensive under disk pressure and provides better disk-usage visibility for diagnosis.

Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No need to test

Unit test:

  • env GOPATH=/Users/xiaoli/go GOSUMDB=sum.golang.org go test -run '^TestRiskOfDiskFull$' -count=1 -tags=intest,deadlock ./pkg/ddl/ingest
  • env GOPATH=/Users/xiaoli/go GOSUMDB=sum.golang.org go test -run '^TestSlotManager$' -count=1 -tags=intest,deadlock ./pkg/dxf/framework/taskexecutor
  • env GOPATH=/Users/xiaoli/go GOSUMDB=sum.golang.org go test -run '^(TestBackfillingSchedulerLocalMode|TestBackfillTaskMetaVersion)$' -count=1 -tags=intest,deadlock ./pkg/ddl

Side effects

  • Performance regression: Consumes more CPU
  • Performance regression: Consumes more Memory
  • Breaking backward compatibility

Documentation

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

Release note

ADD INDEX` with local sort now checks TiDB worker local disk space before backfill starts and fails fast when the remaining disk is insufficient for the local-sort workload plus the extra 10% headroom reserved for partial import.

Summary by CodeRabbit

  • New Features
    • Added local-sort backfill disk-usage sampling with detailed structured summaries to improve operational visibility.
    • Implemented local ingest free-disk validation for local-sort backfill startup by accounting for tracked running jobs and required slot-based reservations.
    • Exposed an executor task slots snapshot API to support disk requirement calculation.
  • Tests
    • Extended unit tests to cover local-sort free-disk check scenarios and executor task slots snapshot behavior.

@ti-chi-bot ti-chi-bot Bot added the release-note-none Denotes a PR that doesn't merit a release note. label May 12, 2026
@pantheon-ai

pantheon-ai Bot commented May 12, 2026

Copy link
Copy Markdown

@expxiaoli I've received your pull request and will start the review. I'll conduct a thorough review covering code quality, potential issues, and implementation details.

⏳ This process typically takes 10-30 minutes depending on the complexity of the changes.

ℹ️ Learn more details on Pantheon AI.

@ti-chi-bot ti-chi-bot Bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label May 12, 2026
@tiprow

tiprow Bot commented May 12, 2026

Copy link
Copy Markdown

Hi @expxiaoli. Thanks for your PR.

PRs from untrusted users cannot be marked as trusted with /ok-to-test in this repo meaning untrusted PR authors can never trigger tests themselves. Collaborators can still trigger tests on the PR using /test all.

I understand the commands that are listed here.

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.

@coderabbitai

coderabbitai Bot commented May 12, 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

Adds local-sort disk-usage sampling and structured logging during local ingest, worker-side free-disk validation using tracked job requirements, and task-executor slot snapshot APIs with tests.

Changes

Local Sort Disk Monitoring

Layer / File(s) Summary
Sampling and pipeline logging
pkg/ddl/backfilling_read_index.go
Samples disk usage immediately and periodically during local ingest, captures final statistics, and logs pipeline context, capacity data, sampling metadata, and success status.

Worker-side Disk Precheck

Layer / File(s) Summary
DiskRoot usage and validation
pkg/ddl/ingest/disk_root.go, pkg/ddl/ingest/mem_root_test.go, pkg/ddl/ingest/BUILD.bazel
Adds tracked usage access, local-sort disk requirement definitions, capacity checking, detailed errors, and test coverage for disk threshold scenarios.
Backfill initialization precheck
pkg/ddl/backfilling_dist_executor.go
Collects local-sort requirements from running tasks and checks available local disk before initializing local read-index backfill.

Task-Executor Slot Snapshot

Layer / File(s) Summary
Snapshot API and implementation
pkg/dxf/framework/taskexecutor/task_executor.go, pkg/dxf/framework/taskexecutor/slot.go, pkg/dxf/framework/taskexecutor/slot_test.go
Adds task-slot snapshot types and APIs, uses a read-locked slot-manager snapshot, and verifies task IDs and required slots in tests.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested labels: component/statistics

Suggested reviewers: gmhdbjd, wjhuang2016, d3hunter

Poem

🐰 Bytes hop softly through the mill,
Samplers count them, calm and still.
Workers check the space they need,
Slots line up in careful speed,
Logs record each finished deed.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: worker-side local sort disk checking and logging.
Description check ✅ Passed The description matches the template with issue number, problem summary, changes, tests, side effects, documentation, and release note.
Linked Issues check ✅ Passed The PR adds the required worker-side precheck and fails fast unless free disk exceeds the calculated requirement.
Out of Scope Changes check ✅ Passed The extra logging, slot snapshot, helpers, and test updates are all directly supporting the linked local-sort disk check work.
✨ 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.

@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

🧹 Nitpick comments (2)
pkg/ddl/backfilling_read_index.go (2)

120-141: 💤 Low value

Consider documenting the single-use lifecycle constraint.

The start() method has no guard against being called multiple times, which would leak goroutines. While the current usage in runLocalPipeline is safe (called exactly once), documenting this constraint would prevent future misuse.

📝 Suggested approach

Add a doc comment:

+// start begins sampling. Must be called exactly once before stopAndSnapshot().
 func (s *localSortDiskUsageSampler) start() {

Or add a guard:

+	started sync.Once
 
 func (s *localSortDiskUsageSampler) start() {
+	s.started.Do(func() {
 		s.mu.Lock()
 		s.startTime = time.Now()
 		// ... rest of method
+	})
 }
🤖 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 `@pkg/ddl/backfilling_read_index.go` around lines 120 - 141, The start() method
on localSortDiskUsageSampler can be called multiple times and will spawn leaking
goroutines; add a single-use guard or document the lifecycle: modify
localSortDiskUsageSampler.start to check a boolean (e.g., started) protected by
mu (or return early if startTime is non-zero), set started/startTime on the
first call, and avoid re-entering so ticker/goroutine are only created once
(ensure doneCh/stopCh handling remains correct), or alternatively add a doc
comment on localSortDiskUsageSampler.start stating it must only be invoked once.

56-56: 💤 Low value

Consider documenting the sampling interval choice.

A brief comment explaining why 1 second was chosen as the sampling interval would help future maintainers understand the trade-off between sampling accuracy and overhead.

📝 Suggested documentation
+// localSortDiskUsageSampleInterval defines how frequently the sampler
+// checks disk usage during local sort operations. 1 second provides
+// reasonable granularity without measurable overhead.
 const localSortDiskUsageSampleInterval = time.Second
🤖 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 `@pkg/ddl/backfilling_read_index.go` at line 56, Add a short comment above the
constant localSortDiskUsageSampleInterval explaining why a 1 second sampling
interval was chosen (e.g., balances timely disk-usage responsiveness during
sort/backfill monitoring with low CPU/io overhead), mention any trade-offs
(latency vs overhead) and note whether the value is adjustable or tied to other
constants (so maintainers know they can tweak it). This comment should live next
to the declaration of localSortDiskUsageSampleInterval in
backfilling_read_index.go and reference the intent to sample disk usage for
local sort/backfill operations.
🤖 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 `@pkg/ddl/backfilling_read_index.go`:
- Around line 87-109: Add clear concurrency and lifecycle documentation for the
sampler types: describe that localSortDiskUsageSampler is safe for concurrent
use only via its Start/Stop (or sampling goroutine) lifecycle, explain ownership
of stopCh/doneCh, that getUsage is called from a single background goroutine
started by the sampler, and that mu protects
startTime/endTime/sumBytes/sampleCnt/peakBytes/lastBytes which are read by
Snapshot via localSortDiskUsageSnapshot; annotate which fields are only touched
by the background goroutine vs protected by mu and state transitions (e.g.,
Start initializes and launches goroutine, Stop closes stopCh and waits on
doneCh), and document expected calling patterns and thread-safety guarantees for
Snapshot, Start, and Stop using the type names localSortDiskUsageSampler and
localSortDiskUsageSnapshot to make locating the docs easy.

---

Nitpick comments:
In `@pkg/ddl/backfilling_read_index.go`:
- Around line 120-141: The start() method on localSortDiskUsageSampler can be
called multiple times and will spawn leaking goroutines; add a single-use guard
or document the lifecycle: modify localSortDiskUsageSampler.start to check a
boolean (e.g., started) protected by mu (or return early if startTime is
non-zero), set started/startTime on the first call, and avoid re-entering so
ticker/goroutine are only created once (ensure doneCh/stopCh handling remains
correct), or alternatively add a doc comment on localSortDiskUsageSampler.start
stating it must only be invoked once.
- Line 56: Add a short comment above the constant
localSortDiskUsageSampleInterval explaining why a 1 second sampling interval was
chosen (e.g., balances timely disk-usage responsiveness during sort/backfill
monitoring with low CPU/io overhead), mention any trade-offs (latency vs
overhead) and note whether the value is adjustable or tied to other constants
(so maintainers know they can tweak it). This comment should live next to the
declaration of localSortDiskUsageSampleInterval in backfilling_read_index.go and
reference the intent to sample disk usage for local sort/backfill operations.
🪄 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: a8111b14-8d26-4e86-9f6e-fe12483b7e9c

📥 Commits

Reviewing files that changed from the base of the PR and between 173eaf2 and fdad246.

📒 Files selected for processing (1)
  • pkg/ddl/backfilling_read_index.go

Comment thread pkg/ddl/backfilling_read_index.go
@codecov

codecov Bot commented May 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 195 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.5169%. Comparing base (cae12c1) to head (9cede86).

Additional details and impacted files
@@               Coverage Diff                @@
##             master     #68320        +/-   ##
================================================
- Coverage   76.3193%   75.5169%   -0.8024%     
================================================
  Files          2041       2086        +45     
  Lines        559929     582918     +22989     
================================================
+ Hits         427334     440202     +12868     
- Misses       131694     140581      +8887     
- Partials        901       2135      +1234     
Flag Coverage Δ
integration 45.5624% <0.0000%> (+5.8571%) ⬆️

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

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

@ti-chi-bot ti-chi-bot Bot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. release-note Denotes a PR that will be considered when it comes time to generate release notes. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. release-note-none Denotes a PR that doesn't merit a release note. labels May 13, 2026
@expxiaoli expxiaoli changed the title pkg/ddl: log local sort disk usage summary pkg/ddl, pkg/dxf: add local sort disk check and logging for backfill workers May 13, 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: 2

🤖 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 `@pkg/ddl/ingest/disk_root.go`:
- Around line 256-266: The current logic subtracts aggregate used bytes from
aggregate required bytes (allJobsRequiredBytes - allJobsUsedBytes) which lets
one job's extra usage mask another job's shortfall; instead compute per-job
shortfalls and sum them: include the new job by computing newJobReq :=
uint64(newJobRequiredSlots) * LocalSortBytesPerSlot and for each runningJob
compute jobReq := uint64(runningJob.RequiredSlots) * LocalSortBytesPerSlot then
if jobReq > runningJob.UsedBytes add (jobReq - runningJob.UsedBytes) to
allJobsGapBytes (and similarly compare newJobReq to 0/its used if applicable),
remove the aggregate subtraction (allJobsRequiredBytes - allJobsUsedBytes), and
then set totalRequiredBytes := totalCapacityBytes/10 + allJobsGapBytes.
🪄 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: 1178c9d3-c3f4-4495-84cc-f50eae30947c

📥 Commits

Reviewing files that changed from the base of the PR and between fdad246 and 0922ed3.

📒 Files selected for processing (6)
  • pkg/ddl/backfilling_dist_executor.go
  • pkg/ddl/ingest/disk_root.go
  • pkg/ddl/ingest/mem_root_test.go
  • pkg/dxf/framework/taskexecutor/slot.go
  • pkg/dxf/framework/taskexecutor/slot_test.go
  • pkg/dxf/framework/taskexecutor/task_executor.go

Comment thread pkg/ddl/ingest/disk_root.go
Comment thread pkg/ddl/ingest/disk_root.go Outdated
@ti-chi-bot

ti-chi-bot Bot commented Jun 18, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign wjhuang2016 for approval. For more information see the Code Review Process.
Please ensure that each of them provides their approval before proceeding.

The full list of commands accepted by this bot can be found 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 commented Jul 20, 2026

Copy link
Copy Markdown

[FORMAT CHECKER NOTIFICATION]

Notice: To remove the do-not-merge/needs-linked-issue label, please provide the linked issue number on one line in the PR body, for example: Issue Number: close #123 or Issue Number: ref #456.

📖 For more info, you can check the "Contribute Code" section in the development guide.

@ti-chi-bot

ti-chi-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown

@expxiaoli: The following tests 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/mysql-test 9cede86 link true /test mysql-test
idc-jenkins-ci-tidb/check_dev_2 9cede86 link true /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

do-not-merge/needs-linked-issue release-note Denotes a PR that will be considered when it comes time to generate release notes. 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.

ddl: add worker-side disk capacity precheck for DXF local-sort add index

1 participant