Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ddl: Fixed partitioning a non-partitioned table with placement rules #57560

Merged
merged 24 commits into from
Nov 29, 2024

Conversation

mjonss
Copy link
Contributor

@mjonss mjonss commented Nov 20, 2024

What problem does this PR solve?

Issue Number: close #55705

Problem Summary:
When updating the placement rule bundle, the table ID was included both as the table and the partition id.

What changed and how does it work?

Not adding it as partition id for non-partitioned table (which uses the original table as a single partition, hence the same ID).

Also simplified the bundle handling during schema update / ApplyDiff, by removing logic that:

  • first went through all partitions and marked the partition to update the bundle, then went through all partition updates and updated its table

to

  • mark the table directly that it should update the bundle.

For REORGANIZE PARTITION, there the bundles will be updated twice, first with the intermediate set of partitions (both old and new), so that data copying and index creations on the new partitions will follow the correct policies directly, and then with the final partition set, avoiding having to move the data again when the DDL is done.

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.

fixed an issue with partitioning a non-partitioned table with placement rules.

@ti-chi-bot ti-chi-bot bot added do-not-merge/needs-triage-completed release-note Denotes a PR that will be considered when it comes time to generate release notes. needs-cherry-pick-release-8.5 Should cherry pick this PR to release-8.5 branch. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Nov 20, 2024
Copy link

tiprow bot commented Nov 20, 2024

Hi @mjonss. 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.

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.

@mjonss mjonss requested a review from lcwangchao November 20, 2024 10:43

Choose a reason for hiding this comment

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

Copilot reviewed 3 out of 3 changed files in this pull request and generated no suggestions.

end string
}
keys := make([]keyRange, 0, rules)
for k := range m.bundles {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we only need to check the rules inside one bundle just now. If GroupBundle.Override is set to true, it is allowed to have multiple leader rules.

And in one RuleGroup when a rule has Override==true, it should also be skipped.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So the below is OK?

if rule.Role == pd.Leader && !m.bundles[k].Override {
				keys = append(keys, keyRange{start: k + ":" + rule.StartKeyHex, end: k + ":" + rule.EndKeyHex})
			}

Copy link
Collaborator

Choose a reason for hiding this comment

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

We still need to check the rules in one bundle even bundle[k].Override is true, but the current implementation skips all rules in such bundle?

Copy link
Contributor

Choose a reason for hiding this comment

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

We still need to check the rules in one bundle even bundle[k].Override is true

true.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@lcwangchao @xhebox please review the new duplicate leader range check.

Copy link
Collaborator

Choose a reason for hiding this comment

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

So, why not only validating the input bundles one by one? I think the current version does not care the overlaps across different rules.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have changed the logic to only check bundles one by one, and tried to mimic the logic of PDs prepareRulesForApply() and checkApplyRules(), for any other check I created #57693 as a follow up.

Copy link

codecov bot commented Nov 20, 2024

Codecov Report

Attention: Patch coverage is 80.35714% with 22 lines in your changes missing coverage. Please review.

Project coverage is 75.2781%. Comparing base (2125737) to head (c6e1ad0).
Report is 27 commits behind head on master.

Additional details and impacted files
@@               Coverage Diff                @@
##             master     #57560        +/-   ##
================================================
+ Coverage   72.8374%   75.2781%   +2.4406%     
================================================
  Files          1677       1722        +45     
  Lines        464022     478576     +14554     
================================================
+ Hits         337982     360263     +22281     
+ Misses       105168      96226      -8942     
- Partials      20872      22087      +1215     
Flag Coverage Δ
integration 49.5831% <63.3928%> (?)
unit 72.6103% <80.3571%> (+0.3742%) ⬆️

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

Components Coverage Δ
dumpling 52.7673% <ø> (ø)
parser ∅ <ø> (∅)
br 62.1692% <ø> (+16.4686%) ⬆️

pkg/ddl/partition.go Outdated Show resolved Hide resolved
pkg/ddl/placement_policy_test.go Show resolved Hide resolved
@ti-chi-bot ti-chi-bot bot added the needs-1-more-lgtm Indicates a PR needs 1 more LGTM. label Nov 20, 2024
@ti-chi-bot ti-chi-bot bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Nov 20, 2024
@mjonss mjonss added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Nov 20, 2024
@ti-chi-bot ti-chi-bot bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Nov 21, 2024
@mjonss mjonss requested a review from Defined2014 November 21, 2024 00:44
Copy link

ti-chi-bot bot commented Nov 21, 2024

@Defined2014: Your lgtm message is repeated, so it is ignored.

In response to this:

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.

// - not removing any placement rules for removed partitions
// - not leaving anything in case of failure/rollback!
// So we will:
// 1) First write the new bundles including both new and old partitions,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why the new bundles should include old partitions? The old bundles have already defined these rules and still take effects here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, so if the Bundle is overwritten, the older bundle rules will still be in effect?
Like if the first bundle had rules for table id 111, part id 112 and 113, and the new bundle would have table id 111, partition id 113 and 114, would part id 112 still be placed as the old bundle rules or would it be placed without any rules?

Copy link
Contributor

Choose a reason for hiding this comment

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

or would it be placed without any rules?

This, I believe.

// it will filter the rules depends on the interval index override in the same group or the
// group-index override between different groups
// For example, given rules:
// ruleA: group_id: 4, id: 2, override: true
// ruleB: group_id: 4, id: 1, override: true
// ruleC: group_id: 3
// ruleD: group_id: 2
// RuleGroupA: id:4, override: false
// RuleGroupB: id:3, override: true
// RuleGroupC: id:2, override: false
// Finally only ruleA and ruleC will be selected.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A better example:

CREATE TABLE t (a int) partition by range (a) (partition p0 values less than (1000000), partition p1M values less than (2000000)) placement policy pp1;
ALTER TABLE t REORGANIZE PARTITION p1M INTO (PARTITION p1M values less than (2000000), partition p2M values less than (3000000));

During the DDL we would still want the original p1M to follow the table level rule, so we keep it in the bundle.
When the final bundles will be created it will not be included.
Since the table keeps its table id (for REORGANIZE PARTITION) there are no other bundles that covers the inherited table's placement rules for the original partition p1M, which means we need to cover it during the time of the DDL, since it can still be accessed (and double written).

Another alternative would be to create partition level bundles for the old replaced partitions, and let them be removed by GC later, but I think that would qualify for a separate PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the rule bundle check improvements would be better addressed in a separate PR, I will update the check and add a unit test here, but when looking at the code in PD, it looks like the example in the comment for prepareRulesForApply() is wrong, if I'm reading the code correctly, I would expect it to return 'ruleC and ruleD`, since ruleB would override ruleA, and ruleC would override all previous rules, due to its group has override set, and finally ruleD would just be added.

And it does not check any key ranges, neither in this function or in checkApplyRules(), which only checks that there are at least one leader or voter, and max one leader.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The example would be correct if the rules would be ordered in reverse, i.e. according to their GroupID, ID.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have changed the logic to only check bundles one by one, and tried to mimic the logic of PDs prepareRulesForApply() and checkApplyRules(), for any other check I created #57693 as a follow up.

Comment on lines 136 to 145
for i := 1; i < len(keys); i++ {
if keys[i].groupID != keys[j].groupID {
// currently not checking if the group overrides all other groups!
applyKeys = append(applyKeys, keys[j:i]...) // save rules belong to previous groups
j = i
}
if keys[i].override {
j = i // skip all previous rules in the same group
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't understand these codes very well. Should we assume that all rules in the same bundle share the same group ID? If so, we just need to validate the rule.GroupID == bundle.ID

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Niether do I, so I did check what PD is implementing and tried to replicate that.

Since these are additional checks, and copied from pd, I would prefer to only have a limited check, that would still catch the main issue that is fixed in the PR, rather than also adding full check, that is not related to the original issue. I would prefer to have the more thorough check in a separate PR, like what #57693 suggests.

@mjonss
Copy link
Contributor Author

mjonss commented Nov 26, 2024

/retest

Copy link

tiprow bot commented Nov 26, 2024

@mjonss: Cannot trigger testing until a trusted user reviews the PR and leaves an /ok-to-test message.

In response to this:

/retest

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.

Comment on lines 120 to 172
for _, rule := range bundle.Rules {
if rule.GroupID != bundle.ID {
// TODO: also check cross IDs
continue
}
keys = append(keys, keyRange{
groupID: rule.GroupID,
id: rule.ID,
start: rule.StartKeyHex,
end: rule.EndKeyHex,
override: rule.Override,
isLeader: rule.Role == pd.Leader,
})
}
if len(keys) == 0 {
return nil
}
// Skip overridden rules, but only within the bundle, not across groups
applyKeys := keys[:0]
j := 0
for i := 1; i < len(keys); i++ {
if keys[i].override {
j = i // skip all previous rules in the same group
// TODO: Should we only override the matching key range?
}
}
applyKeys = append(applyKeys, keys[j:]...)
if len(applyKeys) == 0 {
return fmt.Errorf(`ERROR 8243 (HY000): "[PD:placement:ErrBuildRuleList]build rule list failed, no rule left`)
}

// Additionally check for range overlapping leaders.
keys = keys[:0]
for i := 0; i < len(applyKeys); i++ {
if applyKeys[i].isLeader {
keys = append(keys, applyKeys[i])
}
}
if len(keys) == 0 {
return nil
}

// Sort on Start, id, end
// Could use pd's placement.sortRules() instead.
sort.Slice(keys, func(i, j int) bool {
if keys[i].start == keys[j].start {
if keys[i].id == keys[j].id {
return keys[i].end < keys[j].end
}
return keys[i].id < keys[j].id
}
return keys[i].start < keys[j].start
})
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe we can make above logic more simple by:

	for _, rule := range bundle.Rules {
		if rule.GroupID != bundle.ID {
			return errors.New(....)
		}
		if rule.Role == pd.Leader && rule.Override {
		        keys = append(keys, keyRange{
			        start:    rule.StartKeyHex,
			        end:      rule.EndKeyHex,
		        })
		}
	}
	if len(keys) == 0 {
		return nil
	}
	// Sort on Start, id, end
	// Could use pd's placement.sortRules() instead.
	sort.Slice(keys, func(i, j int) bool {
		if keys[i].start == keys[j].start {
			return keys[i].end < keys[j].end
		}
		return keys[i].start < keys[j].start
	})

Seems prepareRulesForApply is handling rules in the same range which requires building actual rules for each range. We do not need to do it for simple. We can just check there is no overlap in non-override leader rules

@ti-chi-bot ti-chi-bot bot added lgtm and removed needs-1-more-lgtm Indicates a PR needs 1 more LGTM. labels Nov 28, 2024
Copy link

ti-chi-bot bot commented Nov 28, 2024

[LGTM Timeline notifier]

Timeline:

  • 2024-11-20 14:36:48.070107027 +0000 UTC m=+42395.689761543: ☑️ agreed by Defined2014.
  • 2024-11-28 09:25:21.010524118 +0000 UTC m=+714908.630178634: ☑️ agreed by lcwangchao.

Copy link

ti-chi-bot bot commented Nov 28, 2024

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: Defined2014, lcwangchao, wjhuang2016

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

The pull request process is described here

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 Nov 28, 2024
@mjonss
Copy link
Contributor Author

mjonss commented Nov 28, 2024

/retest

Copy link

tiprow bot commented Nov 28, 2024

@mjonss: Cannot trigger testing until a trusted user reviews the PR and leaves an /ok-to-test message.

In response to this:

/retest

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.

@mjonss
Copy link
Contributor Author

mjonss commented Nov 29, 2024

/retest

Copy link

tiprow bot commented Nov 29, 2024

@mjonss: Cannot trigger testing until a trusted user reviews the PR and leaves an /ok-to-test message.

In response to this:

/retest

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.

@ti-chi-bot ti-chi-bot bot merged commit b2f29ee into pingcap:master Nov 29, 2024
27 checks passed
@ti-chi-bot
Copy link
Member

In response to a cherrypick label: new pull request created to branch release-8.5: #57811.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved lgtm needs-cherry-pick-release-8.5 Should cherry pick this PR to release-8.5 branch. 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.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fail to partition table after changing placement rule
6 participants