Skip to content

Commit

Permalink
bindinfo, record how bindings are created in SQL bindings. (#17254) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
sre-bot authored Jun 2, 2020
1 parent f8069aa commit f590e7d
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 9 deletions.
60 changes: 57 additions & 3 deletions bindinfo/bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,9 @@ func (s *testSuite) TestBindParse(c *C) {
status := "using"
charset := "utf8mb4"
collation := "utf8mb4_bin"
sql := fmt.Sprintf(`INSERT INTO mysql.bind_info(original_sql,bind_sql,default_db,status,create_time,update_time,charset,collation) VALUES ('%s', '%s', '%s', '%s', NOW(), NOW(),'%s', '%s')`,
originSQL, bindSQL, defaultDb, status, charset, collation)
source := bindinfo.Manual
sql := fmt.Sprintf(`INSERT INTO mysql.bind_info(original_sql,bind_sql,default_db,status,create_time,update_time,charset,collation,source) VALUES ('%s', '%s', '%s', '%s', NOW(), NOW(),'%s', '%s', '%s')`,
originSQL, bindSQL, defaultDb, status, charset, collation, source)
tk.MustExec(sql)
bindHandle := bindinfo.NewBindHandle(tk.Se)
err := bindHandle.Update(true)
Expand Down Expand Up @@ -822,7 +823,8 @@ func (s *testSuite) TestEvolveInvalidBindings(c *C) {
tk.MustExec("create table t(a int, b int, index idx_a(a))")
tk.MustExec("create global binding for select * from t where a > 10 using select /*+ USE_INDEX(t) */ * from t where a > 10")
// Manufacture a rejected binding by hacking mysql.bind_info.
tk.MustExec("insert into mysql.bind_info values('select * from t where a > ?', 'select /*+ USE_INDEX(t,idx_a) */ * from t where a > 10', 'test', 'rejected', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '')")
tk.MustExec("insert into mysql.bind_info values('select * from t where a > ?', 'select /*+ USE_INDEX(t,idx_a) */ * from t where a > 10', 'test', 'rejected', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '','" +
bindinfo.Manual + "')")
tk.MustQuery("select bind_sql, status from mysql.bind_info").Sort().Check(testkit.Rows(
"select /*+ USE_INDEX(t) */ * from t where a > 10 using",
"select /*+ USE_INDEX(t,idx_a) */ * from t where a > 10 rejected",
Expand Down Expand Up @@ -1096,3 +1098,55 @@ func (s *testSuite) TestReCreateBindAfterEvolvePlan(c *C) {
tk.MustQuery("select * from t where a >= 4 and b >= 1")
c.Assert(tk.Se.GetSessionVars().StmtCtx.IndexNames[0], Equals, "t:idx_b")
}

func (s *testSuite) TestbindingSource(c *C) {
tk := testkit.NewTestKit(c, s.store)
s.cleanBindingEnv(tk)
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int, index idx_a(a))")

// Test Source for SQL created sql
tk.MustExec("create global binding for select * from t where a > 10 using select * from t ignore index(idx_a) where a > 10")
bindHandle := s.domain.BindHandle()
sql, hash := parser.NormalizeDigest("select * from t where a > ?")
bindData := bindHandle.GetBindRecord(hash, sql, "test")
c.Check(bindData, NotNil)
c.Check(bindData.OriginalSQL, Equals, "select * from t where a > ?")
c.Assert(len(bindData.Bindings), Equals, 1)
bind := bindData.Bindings[0]
c.Assert(bind.Source, Equals, bindinfo.Manual)

// Test Source for evolved sql
tk.MustExec("set @@tidb_evolve_plan_baselines=1")
tk.MustQuery("select * from t where a > 10")
bindHandle.SaveEvolveTasksToStore()
sql, hash = parser.NormalizeDigest("select * from t where a > ?")
bindData = bindHandle.GetBindRecord(hash, sql, "test")
c.Check(bindData, NotNil)
c.Check(bindData.OriginalSQL, Equals, "select * from t where a > ?")
c.Assert(len(bindData.Bindings), Equals, 2)
bind = bindData.Bindings[1]
c.Assert(bind.Source, Equals, bindinfo.Evolve)
tk.MustExec("set @@tidb_evolve_plan_baselines=0")

// Test Source for captured sqls
stmtsummary.StmtSummaryByDigestMap.Clear()
tk.MustExec("set @@tidb_capture_plan_baselines = on")
defer func() {
tk.MustExec("set @@tidb_capture_plan_baselines = off")
}()
tk.MustExec("use test")
c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue)
tk.MustExec("select * from t ignore index(idx_a) where a < 10")
tk.MustExec("select * from t ignore index(idx_a) where a < 10")
tk.MustExec("admin capture bindings")
bindHandle.CaptureBaselines()
sql, hash = parser.NormalizeDigest("select * from t where a < ?")
bindData = bindHandle.GetBindRecord(hash, sql, "test")
c.Check(bindData, NotNil)
c.Check(bindData.OriginalSQL, Equals, "select * from t where a < ?")
c.Assert(len(bindData.Bindings), Equals, 1)
bind = bindData.Bindings[0]
c.Assert(bind.Source, Equals, bindinfo.Capture)
}
7 changes: 7 additions & 0 deletions bindinfo/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ const (
// Rejected means that the bind has been rejected after verify process.
// We can retry it after certain time has passed.
Rejected = "rejected"
// Manual indicates the binding is created by SQL like "create binding for ...".
Manual = "manual"
// Capture indicates the binding is captured by TiDB automatically.
Capture = "capture"
// Evolve indicates the binding is evolved by TiDB from old bindings.
Evolve = "evolve"
)

// Binding stores the basic bind hint info.
Expand All @@ -47,6 +53,7 @@ type Binding struct {
Status string
CreateTime types.Time
UpdateTime types.Time
Source string
Charset string
Collation string
// Hint is the parsed hints, it is used to bind hints to stmt node.
Expand Down
7 changes: 5 additions & 2 deletions bindinfo/handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func (h *BindHandle) Update(fullLoad bool) (err error) {
lastUpdateTime := h.bindInfo.lastUpdateTime
h.bindInfo.Unlock()

sql := "select original_sql, bind_sql, default_db, status, create_time, update_time, charset, collation from mysql.bind_info"
sql := "select original_sql, bind_sql, default_db, status, create_time, update_time, charset, collation, source from mysql.bind_info"
if !fullLoad {
sql += " where update_time > \"" + lastUpdateTime.String() + "\""
}
Expand Down Expand Up @@ -462,6 +462,7 @@ func (h *BindHandle) newBindRecord(row chunk.Row) (string, *BindRecord, error) {
UpdateTime: row.GetTime(5),
Charset: row.GetString(6),
Collation: row.GetString(7),
Source: row.GetString(8),
}
bindRecord := &BindRecord{
OriginalSQL: row.GetString(0),
Expand Down Expand Up @@ -567,7 +568,7 @@ func (h *BindHandle) deleteBindInfoSQL(normdOrigSQL, db, bindSQL string) string
}

func (h *BindHandle) insertBindInfoSQL(orignalSQL string, db string, info Binding) string {
return fmt.Sprintf(`INSERT INTO mysql.bind_info VALUES (%s, %s, %s, %s, %s, %s, %s, %s)`,
return fmt.Sprintf(`INSERT INTO mysql.bind_info VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)`,
expression.Quote(orignalSQL),
expression.Quote(info.BindSQL),
expression.Quote(db),
Expand All @@ -576,6 +577,7 @@ func (h *BindHandle) insertBindInfoSQL(orignalSQL string, db string, info Bindin
expression.Quote(info.UpdateTime.String()),
expression.Quote(info.Charset),
expression.Quote(info.Collation),
expression.Quote(info.Source),
)
}

Expand Down Expand Up @@ -628,6 +630,7 @@ func (h *BindHandle) CaptureBaselines() {
Status: Using,
Charset: charset,
Collation: collation,
Source: Capture,
}
// We don't need to pass the `sctx` because the BindSQL has been validated already.
err = h.AddBindRecord(nil, &BindRecord{OriginalSQL: normalizedSQL, Db: dbName, Bindings: []Binding{binding}})
Expand Down
1 change: 1 addition & 0 deletions executor/bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ func (e *SQLBindExec) createSQLBind() error {
Charset: e.charset,
Collation: e.collation,
Status: bindinfo.Using,
Source: bindinfo.Manual,
}
record := &bindinfo.BindRecord{
OriginalSQL: e.normdOrigSQL,
Expand Down
1 change: 1 addition & 0 deletions executor/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ func (e *ShowExec) fetchShowBind() error {
hint.UpdateTime,
hint.Charset,
hint.Collation,
hint.Source,
})
}
}
Expand Down
2 changes: 1 addition & 1 deletion infoschema/tables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1198,7 +1198,7 @@ func (s *testTableSuite) TestStmtSummaryInternalQuery(c *C) {
tk.MustQuery(`select exec_count, digest_text
from information_schema.statements_summary
where digest_text like "select original_sql , bind_sql , default_db , status%"`).Check(testkit.Rows(
"1 select original_sql , bind_sql , default_db , status , create_time , update_time , charset , collation from mysql . bind_info" +
"1 select original_sql , bind_sql , default_db , status , create_time , update_time , charset , collation , source from mysql . bind_info" +
" where update_time > ? order by update_time"))
}

Expand Down
4 changes: 2 additions & 2 deletions planner/core/planbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -3098,8 +3098,8 @@ func buildShowSchema(s *ast.ShowStmt, isView bool, isSequence bool) (schema *exp
names = []string{"Privilege", "Context", "Comment"}
ftypes = []byte{mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar}
case ast.ShowBindings:
names = []string{"Original_sql", "Bind_sql", "Default_db", "Status", "Create_time", "Update_time", "Charset", "Collation"}
ftypes = []byte{mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeDatetime, mysql.TypeDatetime, mysql.TypeVarchar, mysql.TypeVarchar}
names = []string{"Original_sql", "Bind_sql", "Default_db", "Status", "Create_time", "Update_time", "Charset", "Collation", "Source"}
ftypes = []byte{mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeDatetime, mysql.TypeDatetime, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar}
case ast.ShowAnalyzeStatus:
names = []string{"Table_schema", "Table_name", "Partition_name", "Job_info", "Processed_rows", "Start_time", "State"}
ftypes = []byte{mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeVarchar, mysql.TypeLonglong, mysql.TypeDatetime, mysql.TypeVarchar}
Expand Down
1 change: 1 addition & 0 deletions planner/optimize.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ func handleEvolveTasks(ctx context.Context, sctx sessionctx.Context, br *bindinf
Status: bindinfo.PendingVerify,
Charset: charset,
Collation: collation,
Source: bindinfo.Evolve,
}
globalHandle := domain.GetDomain(sctx).BindHandle()
globalHandle.AddEvolvePlanTask(br.OriginalSQL, br.Db, binding)
Expand Down
11 changes: 11 additions & 0 deletions session/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ const (
update_time timestamp(3) NOT NULL,
charset text NOT NULL,
collation text NOT NULL,
source varchar(10) NOT NULL default 'unknown',
INDEX sql_index(original_sql(1024),default_db(1024)) COMMENT "accelerate the speed when add global binding query",
INDEX time_index(update_time) COMMENT "accelerate the speed when querying with last update time"
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;`
Expand Down Expand Up @@ -386,6 +387,8 @@ const (
version45 = 45
// version46 fix a bug in v3.1.1.
version46 = 46
// version47 add Source to bindings to indicate the way binding created.
version47 = 47
)

var (
Expand Down Expand Up @@ -435,6 +438,7 @@ var (
upgradeToVer44,
upgradeToVer45,
upgradeToVer46,
upgradeToVer47,
}
)

Expand Down Expand Up @@ -1060,6 +1064,13 @@ func upgradeToVer46(s Session, ver int64) {
mustExecute(s, "UPDATE HIGH_PRIORITY mysql.user SET File_priv='Y' where Super_priv='Y'")
}

func upgradeToVer47(s Session, ver int64) {
if ver >= version47 {
return
}
doReentrantDDL(s, "ALTER TABLE mysql.bind_info ADD COLUMN `source` varchar(10) NOT NULL default 'unknown'", infoschema.ErrColumnExists)
}

// updateBootstrapVer updates bootstrap version variable in mysql.TiDB table.
func updateBootstrapVer(s Session) {
// Update bootstrap version.
Expand Down
2 changes: 1 addition & 1 deletion session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -1824,7 +1824,7 @@ func CreateSessionWithDomain(store kv.Storage, dom *domain.Domain) (*session, er

const (
notBootstrapped = 0
currentBootstrapVersion = version46
currentBootstrapVersion = version47
)

func getStoreBootstrapVersion(store kv.Storage) int64 {
Expand Down

0 comments on commit f590e7d

Please sign in to comment.