Skip to content

*: make table attribute labels keyspace-aware (#68410)#69762

Open
ti-chi-bot wants to merge 1 commit into
pingcap:release-nextgen-202603from
ti-chi-bot:cherry-pick-68410-to-release-nextgen-202603
Open

*: make table attribute labels keyspace-aware (#68410)#69762
ti-chi-bot wants to merge 1 commit into
pingcap:release-nextgen-202603from
ti-chi-bot:cherry-pick-68410-to-release-nextgen-202603

Conversation

@ti-chi-bot

@ti-chi-bot ti-chi-bot commented Jul 10, 2026

Copy link
Copy Markdown
Member

This is an automated cherry-pick of #68410

What problem does this PR solve?

Issue Number: ref #67765

Problem Summary:
In NextGen deployments, TiDB can run with a keyspace-aware TiKV codec. Table attributes are persisted as PD region label rules, but the existing rule IDs are generated only from database/table/partition names, for example schema/db/table or schema/db/table/partition.

This is not sufficient in keyspace-aware deployments. Different keyspaces may contain tables with the same database, table, and partition names. Without keyspace information in the table attribute label rule ID, label rules from different keyspaces can collide or be read back together. In addition, the rule key ranges must be encoded with the keyspace-aware TiKV codec so that PD applies the rule to the correct keyspace range.

As a result, table attribute label rules need to be keyspace-aware whenever TiDB is running in NextGen with keyspace metadata.

What changed and how does it work?

This PR makes table attribute label rules keyspace-aware in NextGen deployments when the TiKV codec contains keyspace metadata.

The core change is to centralize table attribute label rule ID generation in pkg/ddl/label:

  • Added label.UseKeyspaceAwareRules(codec).
    • It returns true when TiDB is running in NextGen and the TiKV codec has keyspace metadata.
  • Added label.NewRuleID(codec, dbName, tableName, partName).
    • In classic mode, or when the codec does not carry keyspace metadata, it keeps the existing rule ID format:
      • schema/db/table
      • schema/db/table/partition
    • In NextGen with a keyspace-aware codec, it generates:
      • keyspace/<keyspace-id>/schema/db/table
      • keyspace/<keyspace-id>/schema/db/table/partition

label.Rule.Reset now takes the TiKV codec and uses the centralized rule ID helper. When keyspace-aware rules are enabled, it also adds or updates an internal keyspace=<id> label and encodes rule ranges with codec.EncodeRegionRange(...), so the PD rule points to the correct keyspace range. When keyspace-aware rules are not enabled, it keeps the old rule ID format and the old table prefix range encoding.

All DDL table attribute lifecycle paths now pass the store codec and use the centralized rule ID helper, including:

  • ALTER TABLE ... ATTRIBUTES
  • ALTER TABLE ... PARTITION ... ATTRIBUTES
  • add/drop/truncate/reorganize/exchange partition
  • drop schema/table
  • rename table
  • truncate table
  • recover table

The information schema path is updated accordingly:

  • infosync.GetAllLabelRules now passes the current TiKV codec to the label rule manager.
  • When keyspace-aware rules are enabled, GetAllLabelRules filters PD label rules by the current keyspace prefix, so information_schema.attributes only shows table attribute rules for the current keyspace.
  • When keyspace-aware rules are not enabled, no filtering is applied, preserving the existing behavior.
  • checkRule can parse keyspace-prefixed rule IDs in NextGen.

BR backup/restore merge-option logic now also uses the same centralized rule ID helper, so DDL, backup, and restore use consistent table attribute label rule IDs in both classic and keyspace-aware modes.

For restored user-visible attributes, the internal keyspace label is hidden in NextGen, while classic mode preserves the existing behavior.

Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No need to test
    • I checked and no code files have been changed.

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

Please refer to Release Notes Language Style Guide to write a quality release note.

None

Summary by CodeRabbit

  • New Features

    • Added keyspace-aware handling for placement and label rules in supported deployments.
    • Improved label-rule filtering so only rules for the active keyspace are returned.
    • Information schema now displays restored rule identifiers consistently.
  • Bug Fixes

    • Improved rule updates during backup, restore, rename, partition, truncate, and schema operations.
    • Fixed attribute preservation across multi-database table renames and partition exchanges.
    • Corrected region label formatting when labels are filtered.

@ti-chi-bot ti-chi-bot added do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. release-note-none Denotes a PR that doesn't merit a release note. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. type/cherry-pick-for-release-nextgen-202603 labels Jul 10, 2026
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

TiKV codec context is threaded through label-rule creation, reset, filtering, backup, restore, and DDL flows. Next-generation keyspace-aware IDs, labels, region ranges, and information-schema parsing are added with expanded tests and Bazel wiring.

Changes

Keyspace-aware label contracts

Layer / File(s) Summary
Rule IDs, labels, and region encoding
pkg/ddl/label/rule.go, pkg/ddl/label/attributes.go, pkg/ddl/label/BUILD.bazel
Adds codec-aware rule ID generation/restoration, keyspace labels, conditional region-range encoding, and keyspace-aware attribute serialization.
Contract tests
pkg/ddl/label/rule_test.go, pkg/ddl/label/attributes_test.go
Tests classic and next-generation codecs, keyspace-qualified IDs, labels, encoded ranges, and serialized attributes.

DDL codec propagation

Layer / File(s) Summary
DDL label-rule updates
pkg/ddl/executor.go, pkg/ddl/partition.go, pkg/ddl/schema.go, pkg/ddl/table.go
Passes store codecs through attribute, partition, schema, drop, recover, truncate, rename, and exchange flows for rule ID construction and resets.
DDL attribute coverage
pkg/ddl/attributes_sql_test.go
Adds cross-database rename and exchange-partition assertions for table and partition attributes.

Backup and restore rule updates

Layer / File(s) Summary
Codec-aware merge-option rules
br/pkg/backup/schema.go, br/pkg/restore/snap_client/client.go, br/pkg/backup/BUILD.bazel
Uses store codecs when validating merge options, constructing rule IDs, and resetting restored rules.
Backup rule-ID tests
br/pkg/backup/schema_merge_option_test.go
Generates expected table and partition IDs through label.NewRuleID for format and case-insensitive comparisons.

Filtering and parsing label rules

Layer / File(s) Summary
InfoSync filtering
pkg/domain/infosync/info.go, pkg/domain/infosync/label_manager.go, pkg/domain/infosync/label_manager_test.go, pkg/domain/infosync/BUILD.bazel
Passes codecs into label-rule retrieval and filters rules by the active keyspace in next-generation mode.
Information-schema parsing
pkg/executor/infoschema_reader.go, pkg/executor/infoschema_reader_keyspace_test.go, pkg/executor/BUILD.bazel
Restores public rule IDs and parses keyspace-prefixed IDs with validation and table-ID decoding tests.

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

Sequence Diagram(s)

sequenceDiagram
  participant DDL
  participant TiKVCodec
  participant LabelRule
  participant PD
  participant InfoSchema

  DDL->>TiKVCodec: GetCodec()
  DDL->>LabelRule: NewRuleID(codec) and Reset(codec)
  LabelRule->>PD: Store keyspace-aware rule
  InfoSchema->>PD: GetAllLabelRules(codec)
  PD-->>InfoSchema: Filter rules by keyspace
  InfoSchema-->>InfoSchema: Restore and parse public rule IDs
Loading

Suggested reviewers: D3Hunter, GMHDBJD, windtalker, time-and-fate, YuJuncen

Poem

A rabbit hops where codecs gleam,
Keys wear spaces in a tidy stream.
Rules reset, labels align,
Backup and DDL now share the sign.
“Hop hop!” says Bun, “the ranges are fine!”

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% 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 concisely describes the main change: making table attribute labels keyspace-aware.
Description check ✅ Passed The description covers the required problem, changes, tests, and release note sections, and includes an issue reference.
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
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="Running error: context loading failed: failed to load packages: failed to load packages: failed to load with go/packages: context deadline exceeded"
level=error msg="Timeout exceeded: try increasing it by passing --timeout option"


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.

@ChangRui-Ryan ChangRui-Ryan force-pushed the cherry-pick-68410-to-release-nextgen-202603 branch from f41ba81 to 97f1aec Compare July 10, 2026 07:54
@ti-chi-bot ti-chi-bot Bot added the sig/planner SIG: Planner label Jul 10, 2026
@ti-chi-bot

Copy link
Copy Markdown
Member Author

Cherry-pick conflicts appear resolved; removing the do-not-merge/hold label.

@ti-chi-bot

ti-chi-bot Bot commented Jul 10, 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 gmhdbjd, leavrth, time-and-fate 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 removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jul 10, 2026
@ChangRui-Ryan

Copy link
Copy Markdown
Contributor

/retest

@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)
br/pkg/backup/schema.go (1)

328-375: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider deduplicating partition rule ID computation.

label.NewRuleID(codec, dbName, tableName, def.Name.L) is computed identically in both the collection loop (line 341) and the lookup loop (line 373). Building a map[string]string from partition name to rule ID in the first loop would eliminate the redundant recomputation in the second.

♻️ Optional: reuse partition rule IDs
 // Collect all rule IDs to check (table + partitions if any)
 ruleIDs := []string{ruleID}
+partitionRuleIDs := make(map[string]string)
 if s.tableInfo.Partition != nil && len(s.tableInfo.Partition.Definitions) > 0 {
     for _, def := range s.tableInfo.Partition.Definitions {
         partitionRuleID := label.NewRuleID(codec, dbName, tableName, def.Name.L)
         ruleIDs = append(ruleIDs, partitionRuleID)
+        partitionRuleIDs[def.Name.O] = partitionRuleID
     }
 }

 // ... after fetching rules ...

 if s.tableInfo.Partition != nil && len(s.tableInfo.Partition.Definitions) > 0 {
     for _, def := range s.tableInfo.Partition.Definitions {
-        partitionRuleID := label.NewRuleID(codec, dbName, tableName, def.Name.L)
+        partitionRuleID := partitionRuleIDs[def.Name.O]
         if rule, exists := rules[partitionRuleID]; exists {
🤖 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 `@br/pkg/backup/schema.go` around lines 328 - 375, Deduplicate partition rule
ID computation in checkMergeOptionAllowed by storing each partition’s computed
ID during the initial ruleIDs collection, keyed by partition name or definition.
Reuse those stored IDs when checking partition rules instead of calling
label.NewRuleID again in the lookup loop.
pkg/ddl/label/rule_test.go (1)

118-157: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Good test coverage for keyspace-aware codec behavior.

The test correctly validates V1 (classic), V2 in Classic mode, and V2 in NextGen mode, including partition rules and RestoreRuleID round-tripping. Validating region range keys against codecV2.EncodeRegionRange output rather than hardcoded hex is a solid approach.

One minor observation: the partition rule test at line 156 only checks partitionKey label but doesn't verify that dbKey/tableKey labels were updated to "db2"/"t2" after the reset. Consider adding those assertions for completeness.

🤖 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/label/rule_test.go` around lines 118 - 157, Extend
TestResetWithKeyspaceCodec to verify that partitionRule.Labels contains dbKey
with value "db2" and tableKey with value "t2", alongside the existing
partitionKey assertion, confirming Reset updates all identifying labels.
🤖 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 `@br/pkg/backup/schema.go`:
- Around line 328-375: Deduplicate partition rule ID computation in
checkMergeOptionAllowed by storing each partition’s computed ID during the
initial ruleIDs collection, keyed by partition name or definition. Reuse those
stored IDs when checking partition rules instead of calling label.NewRuleID
again in the lookup loop.

In `@pkg/ddl/label/rule_test.go`:
- Around line 118-157: Extend TestResetWithKeyspaceCodec to verify that
partitionRule.Labels contains dbKey with value "db2" and tableKey with value
"t2", alongside the existing partitionKey assertion, confirming Reset updates
all identifying labels.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 15f747da-6cac-4a24-a618-46849550fec6

📥 Commits

Reviewing files that changed from the base of the PR and between 1f6df34 and 97f1aec.

📒 Files selected for processing (24)
  • br/pkg/backup/BUILD.bazel
  • br/pkg/backup/schema.go
  • br/pkg/backup/schema_merge_option_test.go
  • br/pkg/restore/snap_client/client.go
  • pkg/ddl/attributes_sql_test.go
  • pkg/ddl/executor.go
  • pkg/ddl/label/BUILD.bazel
  • pkg/ddl/label/attributes.go
  • pkg/ddl/label/attributes_test.go
  • pkg/ddl/label/rule.go
  • pkg/ddl/label/rule_test.go
  • pkg/ddl/partition.go
  • pkg/ddl/schema.go
  • pkg/ddl/table.go
  • pkg/domain/infosync/BUILD.bazel
  • pkg/domain/infosync/info.go
  • pkg/domain/infosync/label_manager.go
  • pkg/domain/infosync/label_manager_test.go
  • pkg/executor/BUILD.bazel
  • pkg/executor/importer/BUILD.bazel
  • pkg/executor/infoschema_reader.go
  • pkg/executor/infoschema_reader_keyspace_test.go
  • pkg/infoschema/BUILD.bazel
  • pkg/planner/core/issuetest/BUILD.bazel
💤 Files with no reviewable changes (2)
  • pkg/infoschema/BUILD.bazel
  • pkg/planner/core/issuetest/BUILD.bazel

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

Labels

release-note-none Denotes a PR that doesn't merit a release note. sig/planner SIG: Planner size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. type/cherry-pick-for-release-nextgen-202603

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants