ddl : support alter table xx nocache operations switch a table into uncacheable (#29621)

This commit is contained in:
xiaolunzhou
2021-11-11 17:19:06 +08:00
committed by GitHub
parent 184c3e3649
commit a237e41d9f
7 changed files with 127 additions and 3 deletions

View File

@ -19,6 +19,7 @@ import (
"github.com/pingcap/tidb/ddl"
"github.com/pingcap/tidb/domain"
"github.com/pingcap/tidb/errno"
"github.com/pingcap/tidb/parser/model"
"github.com/pingcap/tidb/parser/terror"
"github.com/pingcap/tidb/util/testkit"
)
@ -35,7 +36,7 @@ func (s *testDBSuite2) TestAlterTableCache(c *C) {
tk.MustGetErrCode("alter table t1 ca", errno.ErrParse)
tk.MustGetErrCode("alter table t2 cache", errno.ErrNoSuchTable)
tk.MustExec("alter table t1 cache")
checkTableCache(c, tk.Se, "test", "t1")
checkTableCacheStatus(c, tk.Se, "test", "t1", model.TableCacheStatusEnable)
tk.MustExec("drop table if exists t1")
/*Test can't skip schema checker*/
tk.MustExec("drop table if exists t1,t2")
@ -110,3 +111,24 @@ func (s *testDBSuite2) TestAlterViewTableCache(c *C) {
tk.MustExec("create view v as select * from cache_view_t")
tk.MustGetErrCode("alter table v cache", errno.ErrWrongObject)
}
func (s *testDBSuite2) TestAlterTableNoCache(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("drop table if exists nocache_t1")
/* Test of cache table */
tk.MustExec("create table nocache_t1 ( n int auto_increment primary key)")
tk.MustExec("alter table nocache_t1 cache")
checkTableCacheStatus(c, tk.Se, "test", "nocache_t1", model.TableCacheStatusEnable)
tk.MustExec("alter table nocache_t1 nocache")
checkTableCacheStatus(c, tk.Se, "test", "nocache_t1", model.TableCacheStatusDisable)
tk.MustExec("drop table if exists t1")
// Test if a table is not exists
tk.MustExec("drop table if exists nocache_t")
tk.MustGetErrCode("alter table nocache_t cache", errno.ErrNoSuchTable)
tk.MustExec("create table nocache_t (a int)")
tk.MustExec("alter table nocache_t nocache")
// Multiple no alter cache is okay
tk.MustExec("alter table nocache_t nocache")
tk.MustExec("alter table nocache_t nocache")
}

View File

@ -6391,13 +6391,15 @@ func checkTableLock(c *C, se session.Session, dbName, tableName string, lockTp m
c.Assert(tb.Meta().Lock, IsNil)
}
}
func checkTableCache(c *C, se session.Session, dbName, tableName string) {
func checkTableCacheStatus(c *C, se session.Session, dbName, tableName string, status model.TableCacheStatusType) {
tb := testGetTableByName(c, se, dbName, tableName)
dom := domain.GetDomain(se)
err := dom.Reload()
c.Assert(err, IsNil)
c.Assert(tb.Meta().TableCacheStatusType, Equals, model.TableCacheStatusEnable)
c.Assert(tb.Meta().TableCacheStatusType, Equals, status)
}
func (s *testDBSuite2) TestDDLWithInvalidTableInfo(c *C) {
tk := testkit.NewTestKit(c, s.store)

View File

@ -2857,6 +2857,8 @@ func (d *ddl) AlterTable(ctx context.Context, sctx sessionctx.Context, ident ast
err = d.AlterTablePartitionOptions(sctx, ident, spec)
case ast.AlterTableCache:
err = d.AlterTableCache(sctx, ident)
case ast.AlterTableNoCache:
err = d.AlterTableNoCache(sctx, ident)
default:
// Nothing to do now.
}
@ -6568,6 +6570,7 @@ func (d *ddl) AlterPlacementPolicy(ctx sessionctx.Context, stmt *ast.AlterPlacem
err = d.callHookOnChanged(err)
return errors.Trace(err)
}
func (d *ddl) AlterTableCache(ctx sessionctx.Context, ti ast.Ident) (err error) {
schema, t, err := d.getSchemaAndTableByIdent(ctx, ti)
if err != nil {
@ -6598,3 +6601,27 @@ func (d *ddl) AlterTableCache(ctx sessionctx.Context, ti ast.Ident) (err error)
err = d.callHookOnChanged(err)
return errors.Trace(err)
}
func (d *ddl) AlterTableNoCache(ctx sessionctx.Context, ti ast.Ident) (err error) {
schema, t, err := d.getSchemaAndTableByIdent(ctx, ti)
if err != nil {
return err
}
// if a table is not in cache state, return directly
if t.Meta().TableCacheStatusType == model.TableCacheStatusDisable {
return nil
}
job := &model.Job{
SchemaID: schema.ID,
SchemaName: schema.Name.L,
TableID: t.Meta().ID,
Type: model.ActionAlterNoCacheTable,
BinlogInfo: &model.HistoryInfo{},
Args: []interface{}{},
}
err = d.doDDLJob(ctx, job)
err = d.callHookOnChanged(err)
return errors.Trace(err)
}

View File

@ -835,6 +835,8 @@ func (w *worker) runDDLJob(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64,
ver, err = onAlterTablePlacement(d, t, job)
case model.ActionAlterCacheTable:
ver, err = onAlterCacheTable(t, job)
case model.ActionAlterNoCacheTable:
ver, err = onAlterNoCacheTable(t, job)
default:
// Invalid job, cancel it.
job.State = model.JobStateCancelled

View File

@ -1477,6 +1477,7 @@ func updateLabelRules(job *model.Job, tblInfo *model.TableInfo, oldRules map[str
patch := label.NewRulePatch(newRules, oldRuleIDs)
return infosync.UpdateLabelRules(context.TODO(), patch)
}
func onAlterCacheTable(t *meta.Meta, job *model.Job) (ver int64, err error) {
tbInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID)
if err != nil {
@ -1519,3 +1520,38 @@ func onAlterCacheTable(t *meta.Meta, job *model.Job) (ver int64, err error) {
}
return ver, err
}
func onAlterNoCacheTable(t *meta.Meta, job *model.Job) (ver int64, err error) {
tbInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID)
if err != nil {
return 0, errors.Trace(err)
}
// If the table is not in the cache state
if tbInfo.TableCacheStatusType == model.TableCacheStatusDisable {
job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tbInfo)
return ver, nil
}
switch tbInfo.TableCacheStatusType {
case model.TableCacheStatusEnable:
// enable -> switching
tbInfo.TableCacheStatusType = model.TableCacheStatusSwitching
ver, err = updateVersionAndTableInfoWithCheck(t, job, tbInfo, true)
if err != nil {
return ver, err
}
case model.TableCacheStatusSwitching:
// switching -> disable
tbInfo.TableCacheStatusType = model.TableCacheStatusDisable
ver, err = updateVersionAndTableInfoWithCheck(t, job, tbInfo, true)
if err != nil {
return ver, err
}
// Finish this job.
job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tbInfo)
default:
job.State = model.JobStateCancelled
err = ErrInvalidDDLState.GenWithStackByArgs("alter table no cache", tbInfo.TableCacheStatusType.String())
}
return ver, err
}

View File

@ -417,6 +417,11 @@ func (s *testTableSuite) TestTable(c *C) {
testCheckTableState(c, d, dbInfo1, tblInfo, model.StatePublic)
testCheckJobDone(c, d, job, true)
checkTableCacheTest(c, d, dbInfo1, tblInfo)
// for alter no cache table
job = testAlterNoCacheTable(c, ctx, d, dbInfo1.ID, tblInfo)
testCheckTableState(c, d, dbInfo1, tblInfo, model.StatePublic)
testCheckJobDone(c, d, job, true)
checkTableNoCacheTest(c, d, dbInfo1, tblInfo)
}
func checkTableCacheTest(c *C, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo) {
@ -432,6 +437,18 @@ func checkTableCacheTest(c *C, d *ddl, dbInfo *model.DBInfo, tblInfo *model.Tabl
c.Assert(err, IsNil)
}
func checkTableNoCacheTest(c *C, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo) {
err := kv.RunInNewTxn(context.Background(), d.store, false, func(ctx context.Context, txn kv.Transaction) error {
t := meta.NewMeta(txn)
info, err := t.GetTable(dbInfo.ID, tblInfo.ID)
c.Assert(err, IsNil)
c.Assert(info, NotNil)
c.Assert(info.TableCacheStatusType, Equals, model.TableCacheStatusDisable)
return nil
})
c.Assert(err, IsNil)
}
func testAlterCacheTable(c *C, ctx sessionctx.Context, d *ddl, newSchemaID int64, tblInfo *model.TableInfo) *model.Job {
job := &model.Job{
@ -449,6 +466,23 @@ func testAlterCacheTable(c *C, ctx sessionctx.Context, d *ddl, newSchemaID int64
return job
}
func testAlterNoCacheTable(c *C, ctx sessionctx.Context, d *ddl, newSchemaID int64, tblInfo *model.TableInfo) *model.Job {
job := &model.Job{
SchemaID: newSchemaID,
TableID: tblInfo.ID,
Type: model.ActionAlterNoCacheTable,
BinlogInfo: &model.HistoryInfo{},
Args: []interface{}{},
}
err := d.doDDLJob(ctx, job)
c.Assert(err, IsNil)
v := getSchemaVer(c, ctx)
checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v})
return job
}
// for drop indexes
func createTestTableForDropIndexes(c *C, ctx sessionctx.Context, d *ddl, dbInfo *model.DBInfo, name string, num int) *model.TableInfo {
tableInfo := testTableInfo(c, d, name, num)

View File

@ -93,6 +93,7 @@ const (
ActionAlterTablePlacement ActionType = 56
ActionAlterCacheTable ActionType = 57
ActionAlterTableStatsOptions ActionType = 58
ActionAlterNoCacheTable ActionType = 59
)
var actionMap = map[ActionType]string{