From d72adf893a138cbab83e464039f33b34ecfa03ea Mon Sep 17 00:00:00 2001 From: xiaodong-ji Date: Wed, 23 Sep 2020 14:56:38 +0800 Subject: [PATCH] DDL: Reduce the impact on DML when executing partition DDL (#19991) --- ddl/db_partition_test.go | 16 ++++++++++++++++ ddl/ddl_worker.go | 16 ++++++++++++++++ infoschema/builder.go | 11 ++++++++++- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/ddl/db_partition_test.go b/ddl/db_partition_test.go index 701a0a3780..098b64d131 100644 --- a/ddl/db_partition_test.go +++ b/ddl/db_partition_test.go @@ -2204,6 +2204,22 @@ func (s *testIntegrationSuite3) TestPartitionErrorCode(c *C) { tk.MustGetErrCode("alter table t_part rebuild partition p0,p1;", tmysql.ErrUnsupportedDDLOperation) tk.MustGetErrCode("alter table t_part remove partitioning;", tmysql.ErrUnsupportedDDLOperation) tk.MustGetErrCode("alter table t_part repair partition p1;", tmysql.ErrUnsupportedDDLOperation) + + // Reduce the impact on DML when executing partition DDL + tk1 := testkit.NewTestKit(c, s.store) + tk1.MustExec("use test") + tk1.MustExec("drop table if exists t;") + tk1.MustExec(`create table t(id int primary key) + partition by hash(id) partitions 4;`) + tk1.MustExec("begin") + tk1.MustExec("insert into t values(1);") + + tk2 := testkit.NewTestKit(c, s.store) + tk2.MustExec("use test") + tk2.MustExec("alter table t truncate partition p0;") + + _, err = tk1.Exec("commit") + c.Assert(err, IsNil) } func (s *testIntegrationSuite5) TestConstAndTimezoneDepent(c *C) { diff --git a/ddl/ddl_worker.go b/ddl/ddl_worker.go index 62bf3d9e59..3e858d8a2d 100644 --- a/ddl/ddl_worker.go +++ b/ddl/ddl_worker.go @@ -865,6 +865,22 @@ func updateSchemaVersion(t *meta.Meta, job *model.Job) (int64, error) { OldTableID: ptTableID, } diff.AffectedOpts = affects + case model.ActionTruncateTablePartition: + var oldIDs []int64 + err = job.DecodeArgs(&oldIDs) + if err != nil { + return 0, errors.Trace(err) + } + diff.TableID = job.TableID + affects := make([]*model.AffectedOption, len(oldIDs)) + for i := 0; i < len(oldIDs); i++ { + affects[i] = &model.AffectedOption{ + SchemaID: job.SchemaID, + TableID: oldIDs[i], + OldTableID: oldIDs[i], + } + } + diff.AffectedOpts = affects default: diff.TableID = job.TableID } diff --git a/infoschema/builder.go b/infoschema/builder.go index 6416c6f226..b40b696a04 100644 --- a/infoschema/builder.go +++ b/infoschema/builder.go @@ -119,6 +119,13 @@ func (b *Builder) ApplyDiff(m *meta.Meta, diff *model.SchemaDiff) ([]int64, erro } if diff.AffectedOpts != nil { for _, opt := range diff.AffectedOpts { + // Reduce the impact on DML when executing partition DDL. eg. + // While session 1 performs the DML operation associated with partition 1, + // the TRUNCATE operation of session 2 on partition 2 does not cause the operation of session 1 to fail. + if diff.Type == model.ActionTruncateTablePartition { + tblIDs = append(tblIDs, opt.OldTableID) + continue + } var err error affectedDiff := &model.SchemaDiff{ Version: diff.Version, @@ -263,7 +270,9 @@ func (b *Builder) applyCreateTable(m *meta.Meta, dbInfo *model.DBInfo, tableID i fmt.Sprintf("(Table ID %d)", tableID), ) } - affected = appendAffectedIDs(affected, tblInfo) + if tp != model.ActionTruncateTablePartition { + affected = appendAffectedIDs(affected, tblInfo) + } // Failpoint check whether tableInfo should be added to repairInfo. // Typically used in repair table test to load mock `bad` tableInfo into repairInfo.