ddl : support alter table xx nocache operations switch a table into uncacheable (#29621)
This commit is contained in:
@ -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")
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
36
ddl/table.go
36
ddl/table.go
@ -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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -93,6 +93,7 @@ const (
|
||||
ActionAlterTablePlacement ActionType = 56
|
||||
ActionAlterCacheTable ActionType = 57
|
||||
ActionAlterTableStatsOptions ActionType = 58
|
||||
ActionAlterNoCacheTable ActionType = 59
|
||||
)
|
||||
|
||||
var actionMap = map[ActionType]string{
|
||||
|
||||
Reference in New Issue
Block a user