Skip to content

Commit 7b8c91d

Browse files
authored
ddl: clear MDL related tables for create view (#53944)
ref #53246
1 parent 3fcf785 commit 7b8c91d

File tree

5 files changed

+52
-1
lines changed

5 files changed

+52
-1
lines changed

pkg/ddl/job_table.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ func (s *jobScheduler) startDispatch() error {
421421
if err := s.checkAndUpdateClusterState(false); err != nil {
422422
continue
423423
}
424+
failpoint.InjectCall("beforeAllLoadDDLJobAndRun")
424425
s.loadDDLJobAndRun(se, s.generalDDLWorkerPool, s.getGeneralJob)
425426
s.loadDDLJobAndRun(se, s.reorgWorkerPool, s.getReorgJob)
426427
}

pkg/ddl/job_table_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,3 +228,38 @@ func TestUpgradingRelatedJobState(t *testing.T) {
228228
dom.DDL().StateSyncer().UpdateGlobalState(context.Background(), &syncer.StateInfo{State: syncer.StateNormalRunning})
229229
}
230230
}
231+
232+
func TestGeneralDDLWithQuery(t *testing.T) {
233+
store, _ := testkit.CreateMockStoreAndDomain(t)
234+
235+
tk := testkit.NewTestKit(t, store)
236+
tk.MustExec("use test")
237+
tk.MustExec("CREATE TABLE t (id INT NOT NULL);")
238+
239+
var beforeRunCh = make(chan struct{})
240+
testfailpoint.EnableCall(t, "github.com/pingcap/tidb/pkg/ddl/beforeAllLoadDDLJobAndRun", func() {
241+
<-beforeRunCh
242+
})
243+
var ch = make(chan struct{})
244+
testfailpoint.EnableCall(t, "github.com/pingcap/tidb/pkg/ddl/waitJobSubmitted", func() {
245+
<-ch
246+
})
247+
// 2 general DDLs shouldn't be blocked by each other for MDL, i.e. the "create view xx from select xxx"
248+
// should not fill the MDL related tables.
249+
var wg util.WaitGroupWrapper
250+
wg.Run(func() {
251+
tk := testkit.NewTestKit(t, store)
252+
tk.MustExec("use test")
253+
tk.MustExec("alter table t add column b int")
254+
})
255+
ch <- struct{}{}
256+
wg.Run(func() {
257+
tk := testkit.NewTestKit(t, store)
258+
tk.MustExec("use test")
259+
tk.MustExec("create view v as select * from t")
260+
})
261+
ch <- struct{}{}
262+
tk.MustQuery("select count(1) from mysql.tidb_ddl_job").Check(testkit.Rows("2"))
263+
close(beforeRunCh)
264+
wg.Wait()
265+
}

pkg/executor/ddl.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ func (e *DDLExec) executeCreateView(ctx context.Context, s *ast.CreateViewStmt)
309309
return exeerrors.ErrViewInvalid.GenWithStackByArgs(s.ViewName.Schema.L, s.ViewName.Name.L)
310310
}
311311

312+
e.Ctx().GetSessionVars().ClearRelatedTableForMDL()
312313
return domain.GetDomain(e.Ctx()).DDL().CreateView(e.Ctx(), s)
313314
}
314315

pkg/planner/core/preprocess.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,9 @@ const (
148148
inPrepare preprocessorFlag = 1 << iota
149149
// inTxnRetry is set when visiting in transaction retry.
150150
inTxnRetry
151-
// inCreateOrDropTable is set when visiting create/drop table statement.
151+
// inCreateOrDropTable is set when visiting create/drop table/view/sequence,
152+
// rename table, alter table add foreign key, and BR restore.
153+
// TODO need a better name to clarify it's meaning
152154
inCreateOrDropTable
153155
// parentIsJoin is set when visiting node's parent is join.
154156
parentIsJoin
@@ -927,6 +929,8 @@ func (p *preprocessor) checkCreateTableGrammar(stmt *ast.CreateTableStmt) {
927929
}
928930
if stmt.Select != nil {
929931
// FIXME: a temp error noticing 'not implemented' (issue 4754)
932+
// Note: if we implement it later, please clear it's MDL related tables for
933+
// it like what CREATE VIEW does.
930934
p.err = errors.New("'CREATE TABLE ... SELECT' is not implemented yet")
931935
return
932936
} else if len(stmt.Cols) == 0 && stmt.ReferTable == nil {

pkg/sessionctx/variable/session.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3636,6 +3636,16 @@ func (s *SessionVars) GetRelatedTableForMDL() *sync.Map {
36363636
return s.TxnCtx.relatedTableForMDL
36373637
}
36383638

3639+
// ClearRelatedTableForMDL clears the related table for MDL.
3640+
// related tables for MDL is filled during build logical plan or Preprocess for all DataSources,
3641+
// even for queries inside DDLs like `create view as select xxx` and `create table as select xxx`.
3642+
// it should be cleared before we execute the DDL statement.
3643+
func (s *SessionVars) ClearRelatedTableForMDL() {
3644+
s.TxnCtx.tdmLock.Lock()
3645+
defer s.TxnCtx.tdmLock.Unlock()
3646+
s.TxnCtx.relatedTableForMDL = nil
3647+
}
3648+
36393649
// EnableForceInlineCTE returns the session variable enableForceInlineCTE
36403650
func (s *SessionVars) EnableForceInlineCTE() bool {
36413651
return s.enableForceInlineCTE

0 commit comments

Comments
 (0)