Skip to content

Commit

Permalink
bindinfo: physically delete previous binding when recreating a binding (
Browse files Browse the repository at this point in the history
  • Loading branch information
eurekaka authored and asiafrank committed Dec 8, 2020
1 parent 74817dc commit 180e4d5
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 8 deletions.
29 changes: 29 additions & 0 deletions bindinfo/bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1710,6 +1710,35 @@ func (s *testSuite) TestIssue19836(c *C) {
tk.MustQuery("explain for connection " + strconv.FormatUint(tk.Se.ShowProcess().ID, 10)).Check(explainResult)
}

func (s *testSuite) TestReCreateBind(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.MustQuery("select * from mysql.bind_info").Check(testkit.Rows())
tk.MustQuery("show global bindings").Check(testkit.Rows())

tk.MustExec("create global binding for select * from t using select * from t")
tk.MustQuery("select original_sql, status from mysql.bind_info").Check(testkit.Rows(
"select * from t using",
))
rows := tk.MustQuery("show global bindings").Rows()
c.Assert(len(rows), Equals, 1)
c.Assert(rows[0][0], Equals, "select * from t")
c.Assert(rows[0][3], Equals, "using")

tk.MustExec("create global binding for select * from t using select * from t")
tk.MustQuery("select original_sql, status from mysql.bind_info").Check(testkit.Rows(
"select * from t using",
))
rows = tk.MustQuery("show global bindings").Rows()
c.Assert(len(rows), Equals, 1)
c.Assert(rows[0][0], Equals, "select * from t")
c.Assert(rows[0][3], Equals, "using")
}

func (s *testSuite) TestDMLIndexHintBind(c *C) {
tk := testkit.NewTestKit(c, s.store)
s.cleanBindingEnv(tk)
Expand Down
22 changes: 14 additions & 8 deletions bindinfo/handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,17 +213,22 @@ func (h *BindHandle) CreateBindRecord(sctx sessionctx.Context, record *BindRecor
h.bindInfo.Unlock()
}()

txn, err1 := h.sctx.Context.Txn(true)
if err1 != nil {
return err1
var txn kv.Transaction
txn, err = h.sctx.Context.Txn(true)
if err != nil {
return err
}
now := types.NewTime(types.FromGoTime(oracle.GetTimeFromTS(txn.StartTS())), mysql.TypeTimestamp, 3)

if oldRecord != nil {
for _, binding := range oldRecord.Bindings {
_, err1 = exec.ExecuteInternal(context.TODO(), h.logicalDeleteBindInfoSQL(record.OriginalSQL, record.Db, now, binding.BindSQL))
// Binding recreation should physically delete previous bindings, since marking them as deleted may
// cause unexpected binding caches if there are concurrent CREATE BINDING on multiple tidb instances,
// because the record with `using` status is not guaranteed to have larger update_time than those records
// with `deleted` status.
_, err = exec.ExecuteInternal(context.TODO(), h.deleteBindInfoSQL(record.OriginalSQL, record.Db, binding.BindSQL))
if err != nil {
return err1
return err
}
}
}
Expand Down Expand Up @@ -290,9 +295,10 @@ func (h *BindHandle) AddBindRecord(sctx sessionctx.Context, record *BindRecord)
h.bindInfo.Unlock()
}()

txn, err1 := h.sctx.Context.Txn(true)
if err1 != nil {
return err1
var txn kv.Transaction
txn, err = h.sctx.Context.Txn(true)
if err != nil {
return err
}

if duplicateBinding != nil {
Expand Down

0 comments on commit 180e4d5

Please sign in to comment.