diff --git a/ddl/ddl_worker.go b/ddl/ddl_worker.go index 68fb3f8f83f91..3866e0614e98f 100644 --- a/ddl/ddl_worker.go +++ b/ddl/ddl_worker.go @@ -482,6 +482,9 @@ func (w *worker) handleDDLJobQueue(d *ddlCtx) error { // And the job state is rollback done, it means the job was already finished, also shouldn't discard too. // Otherwise, we should discard the KV modification when running job. txn.Discard() + // If error happens after updateSchemaVersion(), then the schemaVer is updated. + // Result in the retry duration is up to 2 * lease. + schemaVer = 0 } err = w.updateDDLJob(t, job, runJobErr != nil) if err = w.handleUpdateJobError(t, job, err); err != nil { diff --git a/ddl/mock.go b/ddl/mock.go index 72cc1f5a8d95f..1af1cce33a368 100644 --- a/ddl/mock.go +++ b/ddl/mock.go @@ -19,6 +19,7 @@ import ( "time" "github.com/pingcap/errors" + "github.com/pingcap/failpoint" "github.com/pingcap/parser/ast" "github.com/pingcap/parser/charset" "github.com/pingcap/parser/model" @@ -105,6 +106,11 @@ func (s *MockSchemaSyncer) OwnerCheckAllVersions(ctx context.Context, latestVer for { select { case <-ctx.Done(): + failpoint.Inject("checkOwnerCheckAllVersionsWaitTime", func(v failpoint.Value) { + if v.(bool) { + panic("shouldn't happen") + } + }) return errors.Trace(ctx.Err()) case <-ticker.C: ver := atomic.LoadInt64(&s.selfSchemaVersion) diff --git a/ddl/serial_test.go b/ddl/serial_test.go index 7e9c2c4b3b991..72c064a0add0b 100644 --- a/ddl/serial_test.go +++ b/ddl/serial_test.go @@ -1146,3 +1146,20 @@ func (s *testSerialSuite) TestForbidUnsupportedCollations(c *C) { // mustGetUnsupportedCollation("create database ucd collate utf8mb4_unicode_ci", errMsgUnsupportedUnicodeCI) // mustGetUnsupportedCollation("alter table t convert to collate utf8mb4_unicode_ci", "utf8mb4_unicode_ci") } + +func (s *testSerialSuite) TestCreateTableNoBlock(c *C) { + tk := testkit.NewTestKitWithInit(c, s.store) + c.Assert(failpoint.Enable("github.com/pingcap/tidb/ddl/checkOwnerCheckAllVersionsWaitTime", `return(true)`), IsNil) + defer func() { + c.Assert(failpoint.Disable("github.com/pingcap/tidb/ddl/checkOwnerCheckAllVersionsWaitTime"), IsNil) + }() + save := variable.GetDDLErrorCountLimit() + variable.SetDDLErrorCountLimit(1) + defer func() { + variable.SetDDLErrorCountLimit(save) + }() + + tk.MustExec("drop table if exists t") + _, err := tk.Exec("create table t(a int)") + c.Assert(err, NotNil) +} diff --git a/ddl/table.go b/ddl/table.go index 6f080e1103b83..550da191c52a2 100644 --- a/ddl/table.go +++ b/ddl/table.go @@ -75,6 +75,13 @@ func onCreateTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) if err != nil { return ver, errors.Trace(err) } + + failpoint.Inject("checkOwnerCheckAllVersionsWaitTime", func(val failpoint.Value) { + if val.(bool) { + failpoint.Return(ver, errors.New("mock create table error")) + } + }) + // Finish this job. job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tbInfo) asyncNotifyEvent(d, &util.Event{Tp: model.ActionCreateTable, TableInfo: tbInfo})