Skip to content

Commit deeb433

Browse files
authored
planner: skip MDL when analyzing table (#50928) (#53050)
close #47475
1 parent 0695f1e commit deeb433

File tree

3 files changed

+103
-6
lines changed

3 files changed

+103
-6
lines changed

ddl/metadatalocktest/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ go_test(
77
"mdl_test.go",
88
],
99
flaky = True,
10-
shard_count = 32,
10+
shard_count = 34,
1111
deps = [
1212
"//config",
1313
"//ddl",

ddl/metadatalocktest/mdl_test.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,90 @@ func TestMDLAutoCommitReadOnly(t *testing.T) {
392392
require.Greater(t, ts1, ts2)
393393
}
394394

395+
func TestMDLAnalyze(t *testing.T) {
396+
store, dom := testkit.CreateMockStoreAndDomain(t)
397+
sv := server.CreateMockServer(t, store)
398+
399+
sv.SetDomain(dom)
400+
dom.InfoSyncer().SetSessionManager(sv)
401+
defer sv.Close()
402+
403+
conn1 := server.CreateMockConn(t, sv)
404+
tk := testkit.NewTestKitWithSession(t, store, conn1.Context().Session)
405+
conn2 := server.CreateMockConn(t, sv)
406+
tkDDL := testkit.NewTestKitWithSession(t, store, conn2.Context().Session)
407+
tk.MustExec("use test")
408+
tk.MustExec("set global tidb_enable_metadata_lock=1")
409+
tk.MustExec("create table t(a int);")
410+
tk.MustExec("insert into t values(1);")
411+
412+
var wg sync.WaitGroup
413+
wg.Add(2)
414+
var ts2 time.Time
415+
var ts1 time.Time
416+
417+
go func() {
418+
tk.MustExec("begin")
419+
tk.MustExec("analyze table t;")
420+
tk.MustQuery("select sleep(2);")
421+
tk.MustExec("commit")
422+
ts1 = time.Now()
423+
wg.Done()
424+
}()
425+
426+
go func() {
427+
tkDDL.MustExec("alter table test.t add column b int;")
428+
ts2 = time.Now()
429+
wg.Done()
430+
}()
431+
432+
wg.Wait()
433+
require.Greater(t, ts1, ts2)
434+
}
435+
436+
func TestMDLAnalyzePartition(t *testing.T) {
437+
store, dom := testkit.CreateMockStoreAndDomain(t)
438+
sv := server.CreateMockServer(t, store)
439+
440+
sv.SetDomain(dom)
441+
dom.InfoSyncer().SetSessionManager(sv)
442+
defer sv.Close()
443+
444+
conn1 := server.CreateMockConn(t, sv)
445+
tk := testkit.NewTestKitWithSession(t, store, conn1.Context().Session)
446+
conn2 := server.CreateMockConn(t, sv)
447+
tkDDL := testkit.NewTestKitWithSession(t, store, conn2.Context().Session)
448+
tk.MustExec("use test")
449+
tk.MustExec("set @@tidb_partition_prune_mode='dynamic'")
450+
tk.MustExec("set global tidb_enable_metadata_lock=1")
451+
tk.MustExec("create table t(a int) partition by range(a) ( PARTITION p0 VALUES LESS THAN (0), PARTITION p1 VALUES LESS THAN (100), PARTITION p2 VALUES LESS THAN MAXVALUE );")
452+
tk.MustExec("insert into t values(1), (2), (3), (4);")
453+
454+
var wg sync.WaitGroup
455+
wg.Add(2)
456+
var ts2 time.Time
457+
var ts1 time.Time
458+
459+
go func() {
460+
tk.MustExec("begin")
461+
tk.MustExec("analyze table t;")
462+
tk.MustExec("analyze table t partition p1;")
463+
tk.MustQuery("select sleep(2);")
464+
tk.MustExec("commit")
465+
ts1 = time.Now()
466+
wg.Done()
467+
}()
468+
469+
go func() {
470+
tkDDL.MustExec("alter table test.t drop partition p2;")
471+
ts2 = time.Now()
472+
wg.Done()
473+
}()
474+
475+
wg.Wait()
476+
require.Greater(t, ts1, ts2)
477+
}
478+
395479
func TestMDLAutoCommitNonReadOnly(t *testing.T) {
396480
store, dom := testkit.CreateMockStoreAndDomain(t)
397481
sv := server.CreateMockServer(t, store)

planner/core/preprocess.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ func Preprocess(ctx context.Context, sctx sessionctx.Context, node ast.Node, pre
139139
return errors.Trace(v.err)
140140
}
141141

142-
type preprocessorFlag uint8
142+
type preprocessorFlag uint64
143143

144144
const (
145145
// inPrepare is set when visiting in prepare statement.
@@ -157,6 +157,8 @@ const (
157157
inSequenceFunction
158158
// initTxnContextProvider is set when we should init txn context in preprocess
159159
initTxnContextProvider
160+
// inAnalyze is set when visiting an analyze statement.
161+
inAnalyze
160162
)
161163

162164
// Make linter happy.
@@ -390,6 +392,8 @@ func (p *preprocessor) Enter(in ast.Node) (out ast.Node, skipChildren bool) {
390392
p.sctx.GetSessionVars().StmtCtx.IsStaleness = true
391393
p.IsStaleness = true
392394
}
395+
case *ast.AnalyzeTableStmt:
396+
p.flag |= inAnalyze
393397
default:
394398
p.flag &= ^parentIsJoin
395399
}
@@ -1573,10 +1577,12 @@ func (p *preprocessor) handleTableName(tn *ast.TableName) {
15731577
if tn.Schema.String() != "" {
15741578
currentDB = tn.Schema.L
15751579
}
1576-
table, err = tryLockMDLAndUpdateSchemaIfNecessary(p.sctx, model.NewCIStr(currentDB), table, p.ensureInfoSchema())
1577-
if err != nil {
1578-
p.err = err
1579-
return
1580+
if !p.skipLockMDL() {
1581+
table, err = tryLockMDLAndUpdateSchemaIfNecessary(p.sctx, model.NewCIStr(currentDB), table, p.ensureInfoSchema())
1582+
if err != nil {
1583+
p.err = err
1584+
return
1585+
}
15801586
}
15811587

15821588
tableInfo := table.Meta()
@@ -1905,3 +1911,10 @@ func tryLockMDLAndUpdateSchemaIfNecessary(sctx sessionctx.Context, dbName model.
19051911
}
19061912
return tbl, nil
19071913
}
1914+
1915+
// skipLockMDL returns true if the preprocessor should skip the lock of MDL.
1916+
func (p *preprocessor) skipLockMDL() bool {
1917+
// because it's a batch process and will do both DML and DDL.
1918+
// skip lock mdl for ANALYZE statement.
1919+
return p.flag&inAnalyze > 0
1920+
}

0 commit comments

Comments
 (0)