Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ddl: add syntax for setting the cache step of auto id explicitly. #15409

Merged
merged 14 commits into from
Apr 10, 2020
105 changes: 105 additions & 0 deletions ddl/db_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package ddl_test
import (
"context"
"fmt"
"strconv"
"strings"
"sync/atomic"
"time"
Expand Down Expand Up @@ -2152,3 +2153,107 @@ func (s *testIntegrationSuite7) TestAddExpressionIndexOnPartition(c *C) {

tk.MustQuery("select * from t;").Check(testkit.Rows("1 'test' 2", "12 'test' 3", "15 'test' 10", "20 'test' 20"))
}

// TestCreateTableWithAutoIdCache test the auto_id_cache table option.
// `auto_id_cache` take effects on handle too when `PKIshandle` is false,
// or even there is no auto_increment column at all.
func (s *testIntegrationSuite3) TestCreateTableWithAutoIdCache(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("USE test;")
tk.MustExec("drop table if exists t;")
tk.MustExec("drop table if exists t1;")

// Test primary key is handle.
tk.MustExec("create table t(a int auto_increment key) auto_id_cache 100")
tblInfo, err := s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
c.Assert(err, IsNil)
c.Assert(tblInfo.Meta().AutoIdCache, Equals, int64(100))
tk.MustExec("insert into t values()")
tk.MustQuery("select * from t").Check(testkit.Rows("1"))
tk.MustExec("delete from t")

// Invalid the allocator cache, insert will trigger a new cache
tk.MustExec("rename table t to t1;")
tk.MustExec("insert into t1 values()")
tk.MustQuery("select * from t1").Check(testkit.Rows("101"))

// Test primary key is not handle.
tk.MustExec("drop table if exists t;")
tk.MustExec("drop table if exists t1;")
tk.MustExec("create table t(a int) auto_id_cache 100")
tblInfo, err = s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
c.Assert(err, IsNil)

tk.MustExec("insert into t values()")
tk.MustQuery("select _tidb_rowid from t").Check(testkit.Rows("1"))
tk.MustExec("delete from t")

// Invalid the allocator cache, insert will trigger a new cache
tk.MustExec("rename table t to t1;")
tk.MustExec("insert into t1 values()")
tk.MustQuery("select _tidb_rowid from t1").Check(testkit.Rows("101"))

// Test both auto_increment and rowid exist.
tk.MustExec("drop table if exists t;")
tk.MustExec("drop table if exists t1;")
tk.MustExec("create table t(a int null, b int auto_increment unique) auto_id_cache 100")
tblInfo, err = s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
c.Assert(err, IsNil)

tk.MustExec("insert into t(b) values(NULL)")
tk.MustQuery("select b, _tidb_rowid from t").Check(testkit.Rows("1 2"))
tk.MustExec("delete from t")

// Invalid the allocator cache, insert will trigger a new cache.
tk.MustExec("rename table t to t1;")
tk.MustExec("insert into t1(b) values(NULL)")
tk.MustQuery("select b, _tidb_rowid from t1").Check(testkit.Rows("101 102"))
tk.MustExec("delete from t1")

// Test alter auto_id_cache.
tk.MustExec("alter table t1 auto_id_cache 200")
tblInfo, err = s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t1"))
c.Assert(err, IsNil)
c.Assert(tblInfo.Meta().AutoIdCache, Equals, int64(200))

tk.MustExec("insert into t1(b) values(NULL)")
tk.MustQuery("select b, _tidb_rowid from t1").Check(testkit.Rows("201 202"))
tk.MustExec("delete from t1")

// Invalid the allocator cache, insert will trigger a new cache.
tk.MustExec("rename table t1 to t;")
tk.MustExec("insert into t(b) values(NULL)")
tk.MustQuery("select b, _tidb_rowid from t").Check(testkit.Rows("401 402"))
tk.MustExec("delete from t")

tk.MustExec("drop table if exists t;")
tk.MustExec("drop table if exists t1;")
tk.MustExec("create table t(a int auto_increment key) auto_id_cache 3")
tblInfo, err = s.dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
c.Assert(err, IsNil)
c.Assert(tblInfo.Meta().AutoIdCache, Equals, int64(3))

// Test insert batch size(4 here) greater than the customized autoid step(3 here).
tk.MustExec("insert into t(a) values(NULL),(NULL),(NULL),(NULL)")
tk.MustQuery("select a from t").Check(testkit.Rows("1", "2", "3", "4"))
tk.MustExec("delete from t")

// Invalid the allocator cache, insert will trigger a new cache.
tk.MustExec("rename table t to t1;")
tk.MustExec("insert into t1(a) values(NULL)")
next := tk.MustQuery("select a from t1").Rows()[0][0].(string)
nextInt, err := strconv.Atoi(next)
c.Assert(err, IsNil)
c.Assert(nextInt, Greater, 5)

// Test auto_id_cache overflows int64.
tk.MustExec("drop table if exists t;")
_, err = tk.Exec("create table t(a int) auto_id_cache = 9223372036854775808")
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "table option auto_id_cache overflows int64")

tk.MustExec("create table t(a int) auto_id_cache = 9223372036854775807")
_, err = tk.Exec("alter table t auto_id_cache = 9223372036854775808")
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "table option auto_id_cache overflows int64")
}
33 changes: 33 additions & 0 deletions ddl/ddl_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1923,6 +1923,12 @@ func handleTableOptions(options []*ast.TableOption, tbInfo *model.TableInfo) err
switch op.Tp {
case ast.TableOptionAutoIncrement:
tbInfo.AutoIncID = int64(op.UintValue)
case ast.TableOptionAutoIdCache:
if op.UintValue > uint64(math.MaxInt64) {
// TODO: Refine this error.
return errors.New("table option auto_id_cache overflows int64")
}
tbInfo.AutoIdCache = int64(op.UintValue)
case ast.TableOptionComment:
tbInfo.Comment = op.StrValue
case ast.TableOptionCompression:
Expand Down Expand Up @@ -2150,6 +2156,12 @@ func (d *ddl) AlterTable(ctx sessionctx.Context, ident ast.Ident, specs []*ast.A
err = d.ShardRowID(ctx, ident, opt.UintValue)
case ast.TableOptionAutoIncrement:
err = d.RebaseAutoID(ctx, ident, int64(opt.UintValue))
case ast.TableOptionAutoIdCache:
if opt.UintValue > uint64(math.MaxInt64) {
// TODO: Refine this error.
return errors.New("table option auto_id_cache overflows int64")
}
err = d.AlterTableAutoIDCache(ctx, ident, int64(opt.UintValue))
case ast.TableOptionComment:
spec.Comment = opt.StrValue
err = d.AlterTableComment(ctx, ident, spec)
Expand Down Expand Up @@ -3394,6 +3406,27 @@ func (d *ddl) AlterTableComment(ctx sessionctx.Context, ident ast.Ident, spec *a
return errors.Trace(err)
}

// AlterTableAutoIDCache updates the table comment information.
func (d *ddl) AlterTableAutoIDCache(ctx sessionctx.Context, ident ast.Ident, newCache int64) error {
schema, tb, err := d.getSchemaAndTableByIdent(ctx, ident)
if err != nil {
return errors.Trace(err)
}

job := &model.Job{
SchemaID: schema.ID,
TableID: tb.Meta().ID,
SchemaName: schema.Name.L,
Type: model.ActionModifyTableAutoIdCache,
BinlogInfo: &model.HistoryInfo{},
Args: []interface{}{newCache},
}

err = d.doDDLJob(ctx, job)
err = d.callHookOnChanged(err)
return errors.Trace(err)
}

// AlterTableCharset changes the table charset and collate.
func (d *ddl) AlterTableCharsetAndCollate(ctx sessionctx.Context, ident ast.Ident, toCharset, toCollate string, needsOverwriteCols bool) error {
// use the last one.
Expand Down
2 changes: 2 additions & 0 deletions ddl/ddl_worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,8 @@ func (w *worker) runDDLJob(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64,
ver, err = w.onShardRowID(d, t, job)
case model.ActionModifyTableComment:
ver, err = onModifyTableComment(t, job)
case model.ActionModifyTableAutoIdCache:
ver, err = onModifyTableAutoIDCache(t, job)
case model.ActionAddTablePartition:
ver, err = onAddTablePartition(d, t, job)
case model.ActionModifyTableCharsetAndCollate:
Expand Down
2 changes: 1 addition & 1 deletion ddl/rollingback.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ func convertJob2RollbackJob(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job)
model.ActionModifyColumn, model.ActionAddForeignKey,
model.ActionDropForeignKey, model.ActionRenameTable,
model.ActionModifyTableCharsetAndCollate, model.ActionTruncateTablePartition,
model.ActionModifySchemaCharsetAndCollate, model.ActionRepairTable:
model.ActionModifySchemaCharsetAndCollate, model.ActionRepairTable, model.ActionModifyTableAutoIdCache:
ver, err = cancelOnlyNotHandledJob(job)
default:
job.State = model.JobStateCancelled
Expand Down
21 changes: 21 additions & 0 deletions ddl/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,27 @@ func onRebaseAutoID(store kv.Storage, t *meta.Meta, job *model.Job) (ver int64,
return ver, nil
}

func onModifyTableAutoIDCache(t *meta.Meta, job *model.Job) (int64, error) {
var cache int64
if err := job.DecodeArgs(&cache); err != nil {
job.State = model.JobStateCancelled
return 0, errors.Trace(err)
}

tblInfo, err := getTableInfoAndCancelFaultJob(t, job, job.SchemaID)
if err != nil {
return 0, errors.Trace(err)
}

tblInfo.AutoIdCache = cache
ver, err := updateVersionAndTableInfo(t, job, tblInfo, true)
if err != nil {
return ver, errors.Trace(err)
}
job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tblInfo)
return ver, nil
}

func (w *worker) onShardRowID(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error) {
var shardRowIDBits uint64
err := job.DecodeArgs(&shardRowIDBits)
Expand Down
4 changes: 4 additions & 0 deletions executor/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,10 @@ func ConstructResultOfShowCreateTable(ctx sessionctx.Context, tableInfo *model.T
}
}

if tableInfo.AutoIdCache != 0 {
fmt.Fprintf(buf, " /*T![auto_id_cache] AUTO_ID_CACHE=%d */", tableInfo.AutoIdCache)
}

if tableInfo.ShardRowIDBits > 0 {
fmt.Fprintf(buf, "/*!90000 SHARD_ROW_ID_BITS=%d ", tableInfo.ShardRowIDBits)
if tableInfo.PreSplitRegions > 0 {
Expand Down
36 changes: 36 additions & 0 deletions executor/show_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,42 @@ func (s *testAutoRandomSuite) TestShowCreateTableAutoRandom(c *C) {
))
}

// Override testAutoRandomSuite to test auto id cache.
func (s *testAutoRandomSuite) TestAutoIdCache(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")

tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int auto_increment key) auto_id_cache = 10")
tk.MustQuery("show create table t").Check(testutil.RowsWithSep("|",
""+
"t CREATE TABLE `t` (\n"+
" `a` int(11) NOT NULL AUTO_INCREMENT,\n"+
" PRIMARY KEY (`a`)\n"+
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![auto_id_cache] AUTO_ID_CACHE=10 */",
))
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int auto_increment unique, b int key) auto_id_cache 100")
tk.MustQuery("show create table t").Check(testutil.RowsWithSep("|",
""+
"t CREATE TABLE `t` (\n"+
" `a` int(11) NOT NULL AUTO_INCREMENT,\n"+
" `b` int(11) NOT NULL,\n"+
" PRIMARY KEY (`b`),\n"+
" UNIQUE KEY `a` (`a`)\n"+
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![auto_id_cache] AUTO_ID_CACHE=100 */",
))
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int key) auto_id_cache 5")
tk.MustQuery("show create table t").Check(testutil.RowsWithSep("|",
""+
"t CREATE TABLE `t` (\n"+
" `a` int(11) NOT NULL,\n"+
" PRIMARY KEY (`a`)\n"+
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin /*T![auto_id_cache] AUTO_ID_CACHE=5 */",
))
}

func (s *testSuite5) TestShowEscape(c *C) {
tk := testkit.NewTestKit(c, s.store)

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ require (
github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989
github.com/pingcap/kvproto v0.0.0-20200409034505-a5af800ca2ef
github.com/pingcap/log v0.0.0-20200117041106-d28c14d3b1cd
github.com/pingcap/parser v0.0.0-20200407074807-436f1c8c4cff
github.com/pingcap/parser v0.0.0-20200410065024-81f3db8e6095
github.com/pingcap/pd/v4 v4.0.0-beta.1.0.20200305072537-61d9f9cc35d3
github.com/pingcap/sysutil v0.0.0-20200408114249-ed3bd6f7fdb1
github.com/pingcap/tidb-tools v4.0.0-beta.1.0.20200306084441-875bd09aa3d5+incompatible
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,8 @@ github.com/pingcap/kvproto v0.0.0-20200409034505-a5af800ca2ef/go.mod h1:IOdRDPLy
github.com/pingcap/log v0.0.0-20191012051959-b742a5d432e9/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8=
github.com/pingcap/log v0.0.0-20200117041106-d28c14d3b1cd h1:CV3VsP3Z02MVtdpTMfEgRJ4T9NGgGTxdHpJerent7rM=
github.com/pingcap/log v0.0.0-20200117041106-d28c14d3b1cd/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8=
github.com/pingcap/parser v0.0.0-20200407074807-436f1c8c4cff h1:FolYHDHFe4y0WXj6A8nxnlFO4f7gRo0XYBew6JNu8Uk=
github.com/pingcap/parser v0.0.0-20200407074807-436f1c8c4cff/go.mod h1:9v0Edh8IbgjGYW2ArJr19E+bvL8zKahsFp+ixWeId+4=
github.com/pingcap/parser v0.0.0-20200410065024-81f3db8e6095 h1:DyL/YbS4r89FmiZd3XbUrpMSsVFtpOZzh1busGKytiI=
github.com/pingcap/parser v0.0.0-20200410065024-81f3db8e6095/go.mod h1:9v0Edh8IbgjGYW2ArJr19E+bvL8zKahsFp+ixWeId+4=
github.com/pingcap/pd/v4 v4.0.0-beta.1.0.20200305072537-61d9f9cc35d3 h1:Yrp99FnjHAEuDrSBql2l0IqCtJX7KwJbTsD5hIArkvk=
github.com/pingcap/pd/v4 v4.0.0-beta.1.0.20200305072537-61d9f9cc35d3/go.mod h1:25GfNw6+Jcr9kca5rtmTb4gKCJ4jOpow2zV2S9Dgafs=
github.com/pingcap/sysutil v0.0.0-20200206130906-2bfa6dc40bcd/go.mod h1:EB/852NMQ+aRKioCpToQ94Wl7fktV+FNnxf3CX/TTXI=
Expand Down
2 changes: 1 addition & 1 deletion infoschema/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (b *Builder) ApplyDiff(m *meta.Meta, diff *model.SchemaDiff) ([]int64, erro
// We try to reuse the old allocator, so the cached auto ID can be reused.
var allocs autoid.Allocators
if tableIDIsValid(oldTableID) {
if oldTableID == newTableID && diff.Type != model.ActionRenameTable && diff.Type != model.ActionRebaseAutoID {
if oldTableID == newTableID && diff.Type != model.ActionRenameTable && diff.Type != model.ActionRebaseAutoID && diff.Type != model.ActionModifyTableAutoIdCache {
allocs, _ = b.is.AllocByID(oldTableID)
}

Expand Down
Loading