From 91da71d68124b9e720180df7e02d90caad42d049 Mon Sep 17 00:00:00 2001 From: Kenan Yao Date: Mon, 1 Feb 2021 14:44:17 +0800 Subject: [PATCH] cherry pick #22568 to release-4.0 Signed-off-by: ti-srebot --- executor/builder.go | 8 +++--- planner/core/cache.go | 3 --- planner/core/cache_test.go | 2 +- planner/core/prepare_test.go | 51 ++++++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 8 deletions(-) diff --git a/executor/builder.go b/executor/builder.go index 4e1fd5a1b4161..aef4c484f5f3e 100644 --- a/executor/builder.go +++ b/executor/builder.go @@ -1315,11 +1315,11 @@ func (b *executorBuilder) getSnapshotTS() (uint64, error) { } snapshotTS := b.ctx.GetSessionVars().SnapshotTS - txn, err := b.ctx.Txn(true) - if err != nil { - return 0, err - } if snapshotTS == 0 { + txn, err := b.ctx.Txn(true) + if err != nil { + return 0, err + } snapshotTS = txn.StartTS() } b.snapshotTS = snapshotTS diff --git a/planner/core/cache.go b/planner/core/cache.go index 106ab9e84fe9a..9f31a08392a81 100644 --- a/planner/core/cache.go +++ b/planner/core/cache.go @@ -67,7 +67,6 @@ type pstmtPlanCacheKey struct { database string connID uint64 pstmtID uint32 - snapshot uint64 schemaVersion int64 sqlMode mysql.SQLMode timezoneOffset int @@ -90,7 +89,6 @@ func (key *pstmtPlanCacheKey) Hash() []byte { key.hash = append(key.hash, dbBytes...) key.hash = codec.EncodeInt(key.hash, int64(key.connID)) key.hash = codec.EncodeInt(key.hash, int64(key.pstmtID)) - key.hash = codec.EncodeInt(key.hash, int64(key.snapshot)) key.hash = codec.EncodeInt(key.hash, key.schemaVersion) key.hash = codec.EncodeInt(key.hash, int64(key.sqlMode)) key.hash = codec.EncodeInt(key.hash, int64(key.timezoneOffset)) @@ -134,7 +132,6 @@ func NewPSTMTPlanCacheKey(sessionVars *variable.SessionVars, pstmtID uint32, sch database: sessionVars.CurrentDB, connID: sessionVars.ConnectionID, pstmtID: pstmtID, - snapshot: sessionVars.SnapshotTS, schemaVersion: schemaVersion, sqlMode: sessionVars.SQLMode, timezoneOffset: timezoneOffset, diff --git a/planner/core/cache_test.go b/planner/core/cache_test.go index 8ff56ddb97e66..9f68dc27f286f 100644 --- a/planner/core/cache_test.go +++ b/planner/core/cache_test.go @@ -39,5 +39,5 @@ func (s *testCacheSuite) SetUpSuite(c *C) { func (s *testCacheSuite) TestCacheKey(c *C) { defer testleak.AfterTest(c)() key := NewPSTMTPlanCacheKey(s.ctx.GetSessionVars(), 1, 1) - c.Assert(key.Hash(), DeepEquals, []byte{0x74, 0x65, 0x73, 0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x74, 0x69, 0x64, 0x62, 0x74, 0x69, 0x6b, 0x76, 0x74, 0x69, 0x66, 0x6c, 0x61, 0x73, 0x68}) + c.Assert(key.Hash(), DeepEquals, []byte{0x74, 0x65, 0x73, 0x74, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x74, 0x69, 0x64, 0x62, 0x74, 0x69, 0x6b, 0x76, 0x74, 0x69, 0x66, 0x6c, 0x61, 0x73, 0x68}) } diff --git a/planner/core/prepare_test.go b/planner/core/prepare_test.go index 6cc66cc195543..73e43afc689ad 100644 --- a/planner/core/prepare_test.go +++ b/planner/core/prepare_test.go @@ -15,6 +15,7 @@ package core_test import ( "context" + "fmt" "math" "strconv" "time" @@ -859,3 +860,53 @@ func (s *testPrepareSerialSuite) TestPrepareCacheWithJoinTable(c *C) { tk.MustQuery("execute stmt using @a").Check(testkit.Rows()) tk.MustQuery("execute stmt using @b").Check(testkit.Rows("a ")) } + +func (s *testPlanSerialSuite) TestPlanCacheSnapshot(c *C) { + store, _, err := newStoreWithBootstrap() + c.Assert(err, IsNil) + tk := testkit.NewTestKit(c, store) + orgEnable := core.PreparedPlanCacheEnabled() + defer func() { + store.Close() + core.SetPreparedPlanCache(orgEnable) + }() + core.SetPreparedPlanCache(true) + + tk.Se, err = session.CreateSession4TestWithOpt(store, &session.Opt{ + PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64), + }) + c.Assert(err, IsNil) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(id int)") + tk.MustExec("insert into t values (1),(2),(3),(4)") + + // For mocktikv, safe point is not initialized, we manually insert it for snapshot to use. + timeSafe := time.Now().Add(-48 * 60 * 60 * time.Second).Format("20060102-15:04:05 -0700 MST") + safePointSQL := `INSERT HIGH_PRIORITY INTO mysql.tidb VALUES ('tikv_gc_safe_point', '%[1]s', '') + ON DUPLICATE KEY + UPDATE variable_value = '%[1]s'` + tk.MustExec(fmt.Sprintf(safePointSQL, timeSafe)) + + tk.MustExec("prepare stmt from 'select * from t where id=?'") + tk.MustExec("set @p = 1") + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustQuery("execute stmt using @p").Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0")) + tk.MustQuery("execute stmt using @p").Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) + + // Record the current tso. + tk.MustExec("begin") + tso := tk.Se.GetSessionVars().TxnCtx.StartTS + tk.MustExec("rollback") + c.Assert(tso > 0, IsTrue) + // Insert one more row with id = 1. + tk.MustExec("insert into t values (1)") + + tk.MustExec(fmt.Sprintf("set @@tidb_snapshot = '%d'", tso)) + tk.MustQuery("select * from t where id = 1").Check(testkit.Rows("1")) + tk.MustQuery("execute stmt using @p").Check(testkit.Rows("1")) + tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) +}