-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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
executor, ddl: support database placement option and partition placement option #28025
Changes from 18 commits
0e96e86
18a9379
8f44cd9
483b82b
214e69f
c7dce67
457ea5f
0dc5a08
8ad82f4
2e49d6b
62633ad
d30b80e
5c3b909
1634795
51cb28c
a181da5
8a76224
936a794
558c468
f65fbb9
1fc2ef0
f612a51
485830b
2f48a14
6183fab
8b70a24
c3d6792
2e8d0fa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -2723,6 +2723,8 @@ func (d *ddl) AlterTable(ctx context.Context, sctx sessionctx.Context, ident ast | |||||
err = d.AlterTableAttributes(sctx, ident, spec) | ||||||
case ast.AlterTablePartitionAttributes: | ||||||
err = d.AlterTablePartitionAttributes(sctx, ident, spec) | ||||||
case ast.AlterTablePartitionOptions: | ||||||
err = d.AlterTablePartitionOptions(sctx, ident, spec) | ||||||
default: | ||||||
// Nothing to do now. | ||||||
} | ||||||
|
@@ -6318,6 +6320,123 @@ func (d *ddl) AlterTablePartitionAttributes(ctx sessionctx.Context, ident ast.Id | |||||
return errors.Trace(err) | ||||||
} | ||||||
|
||||||
func (d *ddl) AlterTablePartitionOptions(ctx sessionctx.Context, ident ast.Ident, spec *ast.AlterTableSpec) (err error) { | ||||||
schema, tb, err := d.getSchemaAndTableByIdent(ctx, ident) | ||||||
if err != nil { | ||||||
return errors.Trace(err) | ||||||
} | ||||||
|
||||||
meta := tb.Meta() | ||||||
if meta.Partition == nil { | ||||||
return errors.Trace(ErrPartitionMgmtOnNonpartitioned) | ||||||
} | ||||||
|
||||||
partitionID, err := tables.FindPartitionByName(meta, spec.PartitionNames[0].L) | ||||||
if err != nil { | ||||||
return errors.Trace(err) | ||||||
} | ||||||
var policyRefInfo *model.PolicyRefInfo | ||||||
var placementSettings *model.PlacementSettings | ||||||
if spec.Options != nil { | ||||||
for _, op := range spec.Options { | ||||||
switch op.Tp { | ||||||
case ast.TableOptionPlacementPolicy: | ||||||
policyRefInfo = &model.PolicyRefInfo{ | ||||||
Name: model.NewCIStr(op.StrValue), | ||||||
} | ||||||
case ast.TableOptionPlacementPrimaryRegion: | ||||||
if placementSettings == nil { | ||||||
placementSettings = &model.PlacementSettings{} | ||||||
} | ||||||
placementSettings.PrimaryRegion = op.StrValue | ||||||
case ast.TableOptionPlacementRegions: | ||||||
if placementSettings == nil { | ||||||
placementSettings = &model.PlacementSettings{} | ||||||
} | ||||||
placementSettings.Regions = op.StrValue | ||||||
case ast.TableOptionPlacementFollowerCount: | ||||||
if placementSettings == nil { | ||||||
placementSettings = &model.PlacementSettings{} | ||||||
} | ||||||
placementSettings.Followers = op.UintValue | ||||||
case ast.TableOptionPlacementVoterCount: | ||||||
if placementSettings == nil { | ||||||
placementSettings = &model.PlacementSettings{} | ||||||
} | ||||||
placementSettings.Voters = op.UintValue | ||||||
case ast.TableOptionPlacementLearnerCount: | ||||||
if placementSettings == nil { | ||||||
placementSettings = &model.PlacementSettings{} | ||||||
} | ||||||
placementSettings.Learners = op.UintValue | ||||||
case ast.TableOptionPlacementSchedule: | ||||||
if placementSettings == nil { | ||||||
placementSettings = &model.PlacementSettings{} | ||||||
} | ||||||
placementSettings.Schedule = op.StrValue | ||||||
case ast.TableOptionPlacementConstraints: | ||||||
if placementSettings == nil { | ||||||
placementSettings = &model.PlacementSettings{} | ||||||
} | ||||||
placementSettings.Constraints = op.StrValue | ||||||
case ast.TableOptionPlacementLeaderConstraints: | ||||||
if placementSettings == nil { | ||||||
placementSettings = &model.PlacementSettings{} | ||||||
} | ||||||
placementSettings.LeaderConstraints = op.StrValue | ||||||
case ast.TableOptionPlacementLearnerConstraints: | ||||||
if placementSettings == nil { | ||||||
placementSettings = &model.PlacementSettings{} | ||||||
} | ||||||
placementSettings.LearnerConstraints = op.StrValue | ||||||
case ast.TableOptionPlacementFollowerConstraints: | ||||||
if placementSettings == nil { | ||||||
placementSettings = &model.PlacementSettings{} | ||||||
} | ||||||
placementSettings.FollowerConstraints = op.StrValue | ||||||
case ast.TableOptionPlacementVoterConstraints: | ||||||
if placementSettings == nil { | ||||||
placementSettings = &model.PlacementSettings{} | ||||||
} | ||||||
placementSettings.VoterConstraints = op.StrValue | ||||||
default: | ||||||
return errors.Trace(errors.New("unknown partition option")) | ||||||
} | ||||||
xhebox marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
} | ||||||
} | ||||||
|
||||||
// Can not use both a placement policy and direct assignment. If you alter specify both in a CREATE TABLE or ALTER TABLE an error will be returned. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||||||
if placementSettings != nil && policyRefInfo != nil { | ||||||
return errors.Trace(ErrPlacementPolicyWithDirectOption.GenWithStackByArgs(policyRefInfo.Name)) | ||||||
} | ||||||
if placementSettings != nil { | ||||||
// check the direct placement option compatibility. | ||||||
if err := checkPolicyValidation(placementSettings); err != nil { | ||||||
return errors.Trace(err) | ||||||
} | ||||||
} | ||||||
if policyRefInfo != nil { | ||||||
policy, ok := ctx.GetInfoSchema().(infoschema.InfoSchema).PolicyByName(policyRefInfo.Name) | ||||||
if !ok { | ||||||
return errors.Trace(infoschema.ErrPlacementPolicyNotExists.GenWithStackByArgs(policyRefInfo.Name)) | ||||||
} | ||||||
policyRefInfo.ID = policy.ID | ||||||
} | ||||||
|
||||||
job := &model.Job{ | ||||||
SchemaID: schema.ID, | ||||||
TableID: meta.ID, | ||||||
SchemaName: schema.Name.L, | ||||||
Type: model.ActionAlterTablePartitionPolicy, | ||||||
BinlogInfo: &model.HistoryInfo{}, | ||||||
Args: []interface{}{partitionID, policyRefInfo, placementSettings}, | ||||||
} | ||||||
|
||||||
err = d.doDDLJob(ctx, job) | ||||||
err = d.callHookOnChanged(err) | ||||||
return errors.Trace(err) | ||||||
} | ||||||
|
||||||
func buildPolicyInfo(name model.CIStr, options []*ast.PlacementOption) (*model.PolicyInfo, error) { | ||||||
policyInfo := &model.PolicyInfo{PlacementSettings: &model.PlacementSettings{}} | ||||||
policyInfo.Name = name | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -534,3 +534,124 @@ func (s *testDBSuite6) TestPolicyCacheAndPolicyDependencyCache(c *C) { | |
c.Assert(dependencies, NotNil) | ||
c.Assert(len(dependencies), Equals, 0) | ||
} | ||
|
||
func (s *testDBSuite6) TestAlterTablePartitionWithPlacementPolicy(c *C) { | ||
tk := testkit.NewTestKit(c, s.store) | ||
defer func() { | ||
tk.MustExec("drop table if exists t1") | ||
tk.MustExec("drop placement policy if exists x") | ||
}() | ||
tk.MustExec("use test") | ||
tk.MustExec("drop table if exists t1") | ||
// Direct placement option: special constraints may be incompatible with common constraint. | ||
tk.MustExec("create table t1 (c int) PARTITION BY RANGE (c) " + | ||
"(PARTITION p0 VALUES LESS THAN (6)," + | ||
"PARTITION p1 VALUES LESS THAN (11)," + | ||
"PARTITION p2 VALUES LESS THAN (16)," + | ||
"PARTITION p3 VALUES LESS THAN (21));") | ||
|
||
tk.MustExec("alter table t1 partition p0 " + | ||
"PRIMARY_REGION=\"cn-east-1\" " + | ||
"REGIONS=\"cn-east-1, cn-east-2\" " + | ||
"FOLLOWERS=2 " + | ||
"FOLLOWER_CONSTRAINTS=\"[+zone=cn-east-1]\" " + | ||
"CONSTRAINTS=\"[+disk=ssd]\"") | ||
|
||
tbl := testGetTableByName(c, tk.Se, "test", "t1") | ||
c.Assert(tbl, NotNil) | ||
ptDef := testGetPartitionDefinitionsByName(c, tk.Se, "test", "t1", "p0") | ||
c.Assert(ptDef.PlacementPolicyRef.Name.L, Equals, "") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the args of json.Unmarshal() will be init , and it seems to me that ptDef.PlacementPolicyRef is nil or "" makes no difference |
||
c.Assert(ptDef.DirectPlacementOpts, NotNil) | ||
|
||
checkFunc := func(policySetting *model.PlacementSettings) { | ||
c.Assert(policySetting.PrimaryRegion, Equals, "cn-east-1") | ||
c.Assert(policySetting.Regions, Equals, "cn-east-1, cn-east-2") | ||
c.Assert(policySetting.Followers, Equals, uint64(2)) | ||
c.Assert(policySetting.FollowerConstraints, Equals, "[+zone=cn-east-1]") | ||
c.Assert(policySetting.Voters, Equals, uint64(0)) | ||
c.Assert(policySetting.VoterConstraints, Equals, "") | ||
c.Assert(policySetting.Learners, Equals, uint64(0)) | ||
c.Assert(policySetting.LearnerConstraints, Equals, "") | ||
c.Assert(policySetting.Constraints, Equals, "[+disk=ssd]") | ||
c.Assert(policySetting.Schedule, Equals, "") | ||
} | ||
checkFunc(ptDef.DirectPlacementOpts) | ||
|
||
//Direct placement option and placement policy can't co-exist. | ||
_, err := tk.Exec("alter table t1 partition p0 " + | ||
"PRIMARY_REGION=\"cn-east-1\" " + | ||
"REGIONS=\"cn-east-1, cn-east-2\" " + | ||
"FOLLOWERS=2 " + | ||
"FOLLOWER_CONSTRAINTS=\"[+zone=cn-east-1]\" " + | ||
"CONSTRAINTS=\"[+disk=ssd]\" " + | ||
"PLACEMENT POLICY=\"x\"") | ||
c.Assert(err, NotNil) | ||
c.Assert(err.Error(), Equals, "[ddl:8240]Placement policy 'x' can't co-exist with direct placement options") | ||
|
||
// Only placement policy should check the policy existence. | ||
tk.MustGetErrCode("alter table t1 partition p0 "+ | ||
"PLACEMENT POLICY=\"x\"", mysql.ErrPlacementPolicyNotExists) | ||
tk.MustExec("create placement policy x " + | ||
"FOLLOWERS=2 ") | ||
tk.MustExec("alter table t1 partition p0 " + | ||
"PLACEMENT POLICY=\"x\"") | ||
|
||
ptDef = testGetPartitionDefinitionsByName(c, tk.Se, "test", "t1", "p0") | ||
c.Assert(ptDef, NotNil) | ||
c.Assert(ptDef.PlacementPolicyRef, NotNil) | ||
c.Assert(ptDef.PlacementPolicyRef.Name.L, Equals, "x") | ||
c.Assert(ptDef.PlacementPolicyRef.ID != 0, Equals, true) | ||
|
||
// Only direct placement options should check the compatibility itself. | ||
_, err = tk.Exec("alter table t1 partition p0 " + | ||
"PRIMARY_REGION=\"cn-east-1\" " + | ||
"REGIONS=\"cn-east-1, cn-east-2\" " + | ||
"FOLLOWERS=2 " + | ||
"FOLLOWER_CONSTRAINTS=\"[+zone=cn-east-1]\" " + | ||
"CONSTRAINTS=\"[+disk=ssd, -zone=cn-east-1]\" ") | ||
c.Assert(err, NotNil) | ||
c.Assert(err.Error(), Equals, "conflicting label constraints: '-zone=cn-east-1' and '+zone=cn-east-1'") | ||
|
||
tk.MustExec("alter table t1 partition p0 " + | ||
"PRIMARY_REGION=\"cn-east-1\" " + | ||
"REGIONS=\"cn-east-1, cn-east-2\" " + | ||
"FOLLOWERS=2 " + | ||
"FOLLOWER_CONSTRAINTS=\"[+zone=cn-east-1]\" " + | ||
"CONSTRAINTS=\"[+disk=ssd]\" ") | ||
|
||
ptDef = testGetPartitionDefinitionsByName(c, tk.Se, "test", "t1", "p0") | ||
c.Assert(ptDef, NotNil) | ||
c.Assert(ptDef.DirectPlacementOpts, NotNil) | ||
|
||
checkFunc = func(policySetting *model.PlacementSettings) { | ||
c.Assert(policySetting.PrimaryRegion, Equals, "cn-east-1") | ||
c.Assert(policySetting.Regions, Equals, "cn-east-1, cn-east-2") | ||
c.Assert(policySetting.Followers, Equals, uint64(2)) | ||
c.Assert(policySetting.FollowerConstraints, Equals, "[+zone=cn-east-1]") | ||
c.Assert(policySetting.Voters, Equals, uint64(0)) | ||
c.Assert(policySetting.VoterConstraints, Equals, "") | ||
c.Assert(policySetting.Learners, Equals, uint64(0)) | ||
c.Assert(policySetting.LearnerConstraints, Equals, "") | ||
c.Assert(policySetting.Constraints, Equals, "[+disk=ssd]") | ||
c.Assert(policySetting.Schedule, Equals, "") | ||
} | ||
checkFunc(ptDef.DirectPlacementOpts) | ||
} | ||
|
||
func testGetPartitionDefinitionsByName(c *C, ctx sessionctx.Context, db string, table string, ptName string) model.PartitionDefinition { | ||
dom := domain.GetDomain(ctx) | ||
// Make sure the table schema is the new schema. | ||
err := dom.Reload() | ||
c.Assert(err, IsNil) | ||
tbl, err := dom.InfoSchema().TableByName(model.NewCIStr(db), model.NewCIStr(table)) | ||
c.Assert(err, IsNil) | ||
c.Assert(tbl, NotNil) | ||
var ptDef model.PartitionDefinition | ||
for _, def := range tbl.Meta().Partition.Definitions { | ||
if ptName == def.Name.L { | ||
ptDef = def | ||
break | ||
} | ||
} | ||
return ptDef | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1292,6 +1292,43 @@ func onAlterTablePartitionAttributes(t *meta.Meta, job *model.Job) (ver int64, e | |
return ver, nil | ||
} | ||
|
||
func onAlterTablePartitionOptions(t *meta.Meta, job *model.Job) (ver int64, err error) { | ||
var partitionID int64 | ||
policyRefInfo := &model.PolicyRefInfo{} | ||
placementSettings := &model.PlacementSettings{} | ||
err = job.DecodeArgs(&partitionID, policyRefInfo, placementSettings) | ||
if err != nil { | ||
job.State = model.JobStateCancelled | ||
return 0, errors.Trace(err) | ||
} | ||
tblInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID) | ||
if err != nil { | ||
return 0, err | ||
} | ||
|
||
ptInfo := tblInfo.GetPartitionInfo() | ||
if ptInfo.GetNameByID(partitionID) == "" { | ||
job.State = model.JobStateCancelled | ||
return 0, errors.Trace(table.ErrUnknownPartition.GenWithStackByArgs("drop?", tblInfo.Name.O)) | ||
} | ||
for idx, ptDef := range ptInfo.Definitions { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
if ptDef.ID == partitionID { | ||
ptDef.DirectPlacementOpts = placementSettings | ||
ptDef.PlacementPolicyRef = policyRefInfo | ||
ptInfo.Definitions[idx] = ptDef | ||
break | ||
} | ||
} | ||
|
||
ver, err = updateVersionAndTableInfo(t, job, tblInfo, true) | ||
if err != nil { | ||
return ver, errors.Trace(err) | ||
} | ||
job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tblInfo) | ||
|
||
return ver, nil | ||
} | ||
|
||
func getOldLabelRules(tblInfo *model.TableInfo, oldSchemaName, oldTableName string) (string, []string, []string, map[string]*label.Rule, error) { | ||
tableRuleID := fmt.Sprintf(label.TableIDFormat, label.IDPrefix, oldSchemaName, oldTableName) | ||
oldRuleIDs := []string{tableRuleID} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For all the Direct Placement options, you can now use
SetDirectPlacementOpt
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done