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

infoschema: don't load table info to get auto_increment value #57296

Merged
merged 5 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion pkg/executor/infoschema_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,11 +242,29 @@ func getAutoIncrementID(
sctx sessionctx.Context,
tblInfo *model.TableInfo,
) int64 {
if raw, ok := is.(*infoschema.SessionExtendedInfoSchema); ok {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this type assertion?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Infoschema that we can get from session is wrapped with SessionExtendedInfoSchema:

func AttachLocalTemporaryTableInfoSchema(sctx variable.SessionVarsProvider, is infoschema.InfoSchema) infoschema.InfoSchema {

v2, ok := raw.InfoSchema.(interface {
TableIsCached(id int64) bool
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we use IsV2 which seems easier to understand? It seems that the v1 tables are all cached.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

})
if ok {
isCached := v2.TableIsCached(tblInfo.ID)
if !isCached {
// Loading table info from kv storage invalidates the cached auto_increment id.
return 0
}
}
}
tbl, ok := is.TableByID(context.Background(), tblInfo.ID)
if !ok {
return 0
}
return tbl.Allocators(sctx.GetTableCtx()).Get(autoid.AutoIncrementType).Base() + 1
alloc := tbl.Allocators(sctx.GetTableCtx()).Get(autoid.AutoIncrementType)
if alloc == nil || alloc.Base() == 0 {
// It may not be loaded yet.
// To show global next autoID, one should use `show table x next_row_id`.
return 0
}
return alloc.Base() + 1
}

func hasPriv(ctx sessionctx.Context, priv mysql.PrivilegeType) bool {
Expand Down
25 changes: 25 additions & 0 deletions pkg/infoschema/infoschema_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,31 @@ func (is *infoschemaV2) IterateAllTableItems(visit func(TableItem) bool) {
})
}

// TableIsCached checks whether the table is cached.
func (is *infoschemaV2) TableIsCached(id int64) (ok bool) {
if !tableIDIsValid(id) {
return false
}

itm, ok := is.searchTableItemByID(id)
if !ok {
return false
}

if isTableVirtual(id) {
if raw, exist := is.Data.specials.Load(itm.dbName.L); exist {
schTbls := raw.(*schemaTables)
_, ok = schTbls.tables[itm.tableName.L]
return ok
}
return false
}

key := tableCacheKey{itm.tableID, itm.schemaVersion}
tbl, found := is.tableCache.Get(key)
return found && tbl != nil
}

// IsSpecialDB tells whether the database is a special database.
func IsSpecialDB(dbName string) bool {
return dbName == util.InformationSchemaName.L ||
Expand Down
3 changes: 2 additions & 1 deletion pkg/infoschema/test/infoschemav2test/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ go_test(
"v2_test.go",
],
flaky = True,
shard_count = 11,
shard_count = 12,
deps = [
"//pkg/domain",
"//pkg/domain/infosync",
"//pkg/infoschema",
"//pkg/infoschema/context",
"//pkg/meta/autoid",
"//pkg/parser/auth",
"//pkg/parser/model",
"//pkg/sessionctx/variable",
Expand Down
24 changes: 24 additions & 0 deletions pkg/infoschema/test/infoschemav2test/v2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/pingcap/tidb/pkg/domain/infosync"
"github.com/pingcap/tidb/pkg/infoschema"
infoschemacontext "github.com/pingcap/tidb/pkg/infoschema/context"
"github.com/pingcap/tidb/pkg/meta/autoid"
"github.com/pingcap/tidb/pkg/parser/auth"
"github.com/pingcap/tidb/pkg/parser/model"
"github.com/pingcap/tidb/pkg/sessionctx/variable"
Expand Down Expand Up @@ -534,3 +535,26 @@ func TestSnapshotInfoschemaReader(t *testing.T) {
sql = fmt.Sprintf("select * from INFORMATION_SCHEMA.TABLES as of timestamp '%s' where table_schema = 'issue55827'", timeStr)
tk.MustQuery(sql).Check(testkit.Rows())
}

func TestInfoSchemaCachedAutoIncrement(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
autoid.SetStep(1)
tk.MustExec("set @@global.tidb_schema_cache_size = 0;")
tk.MustExec("create table t (a int primary key auto_increment);")
autoIncQuery := "select auto_increment from information_schema.tables where table_name = 't' and table_schema = 'test';"

tk.MustQuery(autoIncQuery).Check(testkit.Rows("0"))
tk.MustExec("insert into t values (),(),();")
tk.MustQuery(autoIncQuery).Check(testkit.Rows("4"))

tk.MustExec("set @@global.tidb_schema_cache_size = 1024 * 1024 * 1024;")
tk.MustExec("create table t1 (a int);") // trigger infoschema cache reload
tk.MustQuery(autoIncQuery).Check(testkit.Rows("0"))
tk.MustExec("insert into t values ();")
tk.MustQuery(autoIncQuery).Check(testkit.Rows("5"))
tk.MustExec("set @@global.tidb_schema_cache_size = 0;")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an API you can use to evict table cache directly, although trigger reload can get the same effect.

	is := dom.InfoSchema()
	ok, v2 := infoschema.IsV2(is)
	require.True(t, ok)
	v2.EvictTable(model.NewCIStr("test"), model.NewCIStr("t1"))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The schema is not v2 if we don't reload.

tk.MustExec("drop table t1;") // trigger infoschema cache reload
tk.MustQuery(autoIncQuery).Check(testkit.Rows("0"))
}