diff --git a/bindinfo/bind_test.go b/bindinfo/bind_test.go index 596422d0b5621..94b5ec8d03433 100644 --- a/bindinfo/bind_test.go +++ b/bindinfo/bind_test.go @@ -99,8 +99,8 @@ func (s *testSuite) TearDownTest(c *C) { } func (s *testSuite) cleanBindingEnv(tk *testkit.TestKit) { - tk.MustExec("drop table if exists mysql.bind_info") - tk.MustExec(session.CreateBindInfoTable) + tk.MustExec("truncate table mysql.bind_info") + s.domain.BindHandle().Clear() } func (s *testSuite) TestBindParse(c *C) { @@ -465,3 +465,21 @@ func (s *testSuite) TestErrorBind(c *C) { c.Check(err, IsNil) c.Check(chk.NumRows(), Equals, 0) } + +func (s *testSuite) TestBindingCache(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, b int, index idx(a))") + tk.MustExec("create global binding for select * from t using select * from t use index(idx)") + tk.MustExec("create database tmp") + tk.MustExec("use tmp") + tk.MustExec("create table t(a int, b int, index idx(a))") + tk.MustExec("create global binding for select * from t using select * from t use index(idx)") + + c.Assert(s.domain.BindHandle().Update(false), IsNil) + c.Assert(s.domain.BindHandle().Update(false), IsNil) + res := tk.MustQuery("show global bindings") + c.Assert(len(res.Rows()), Equals, 2) +} diff --git a/bindinfo/handle.go b/bindinfo/handle.go index 739a29726b400..3056996ea6e69 100644 --- a/bindinfo/handle.go +++ b/bindinfo/handle.go @@ -95,7 +95,7 @@ func NewBindHandle(ctx sessionctx.Context) *BindHandle { func (h *BindHandle) Update(fullLoad bool) (err error) { sql := "select original_sql, bind_sql, default_db, status, create_time, update_time, charset, collation from mysql.bind_info" if !fullLoad { - sql += " where update_time >= \"" + h.lastUpdateTime.String() + "\"" + sql += " where update_time > \"" + h.lastUpdateTime.String() + "\"" } // No need to acquire the session context lock for ExecRestrictedSQL, it @@ -358,6 +358,7 @@ func (c cache) removeDeletedBindMeta(hash string, meta *BindMeta, scope string) } } } + c[hash] = metas } // removeStaleBindMetas removes all the stale BindMeta in the cache. @@ -377,12 +378,15 @@ func (c cache) removeStaleBindMetas(hash string, meta *BindMeta, scope string) { } } } + c[hash] = metas } func (c cache) copy() cache { newCache := make(cache, len(c)) for k, v := range c { - newCache[k] = v + bindMetas := make([]*BindMeta, len(v)) + copy(bindMetas, v) + newCache[k] = bindMetas } return newCache } @@ -445,3 +449,10 @@ func (h *BindHandle) logicalDeleteBindInfoSQL(normdOrigSQL, db string, updateTs expression.Quote(normdOrigSQL), expression.Quote(db)) } + +// Clear resets the bind handle. It is used for test. +func (h *BindHandle) Clear() { + h.bindInfo.Store(make(cache)) + h.invalidBindRecordMap.Store(make(map[string]*invalidBindRecordMap)) + h.lastUpdateTime = types.ZeroTimestamp +}