From 489e313aea44a5998ca7e51aea44139020058cdd Mon Sep 17 00:00:00 2001 From: pingcap-github-bot Date: Tue, 14 Apr 2020 22:27:30 +0800 Subject: [PATCH] *: not send tso request when point get with max tso (#11981) (#16336) --- executor/adapter.go | 2 +- planner/optimize.go | 18 ++++++++++++++++++ session/session.go | 13 +++++++++++-- sessionctx/context.go | 2 ++ util/mock/context.go | 4 ++++ 5 files changed, 36 insertions(+), 3 deletions(-) diff --git a/executor/adapter.go b/executor/adapter.go index 073a7bfcb0099..46fd51f1c33fb 100644 --- a/executor/adapter.go +++ b/executor/adapter.go @@ -855,7 +855,7 @@ func (a *ExecStmt) SummaryStmt() { // IsPointGetWithPKOrUniqueKeyByAutoCommit returns true when meets following conditions: // 1. ctx is auto commit tagged // 2. txn is not valid -// 2. plan is point get by pk, or point get by unique index (no double read) +// 3. plan is point get by pk, or point get by unique index (no double read) func IsPointGetWithPKOrUniqueKeyByAutoCommit(ctx sessionctx.Context, p plannercore.Plan) (bool, error) { // check auto commit if !ctx.GetSessionVars().IsAutocommit() { diff --git a/planner/optimize.go b/planner/optimize.go index fabbc0c6281ba..8b007bc1dcb7b 100644 --- a/planner/optimize.go +++ b/planner/optimize.go @@ -15,6 +15,7 @@ package planner import ( "context" + "github.com/pingcap/parser/ast" "github.com/pingcap/tidb/infoschema" "github.com/pingcap/tidb/kv" @@ -30,10 +31,15 @@ func Optimize(ctx context.Context, sctx sessionctx.Context, node ast.Node, is in if _, containTiKV := sctx.GetSessionVars().GetIsolationReadEngines()[kv.TiKV]; containTiKV { fp := plannercore.TryFastPlan(sctx, node) if fp != nil { + if !isPointGetWithoutDoubleRead(sctx, fp) { + sctx.PrepareTxnFuture(ctx) + } return fp, nil } } + sctx.PrepareTxnFuture(ctx) + // build logical plan sctx.GetSessionVars().PlanID = 0 sctx.GetSessionVars().PlanColumnID = 0 @@ -79,6 +85,18 @@ func Optimize(ctx context.Context, sctx sessionctx.Context, node ast.Node, is in return plannercore.DoOptimize(ctx, builder.GetOptFlag(), logic) } +// isPointGetWithoutDoubleRead returns true when meets following conditions: +// 1. ctx is auto commit tagged. +// 2. plan is point get by pk. +func isPointGetWithoutDoubleRead(ctx sessionctx.Context, p plannercore.Plan) bool { + if !ctx.GetSessionVars().IsAutocommit() { + return false + } + + v, ok := p.(*plannercore.PointGetPlan) + return ok && v.IndexInfo == nil +} + func init() { plannercore.OptimizeAstNode = Optimize } diff --git a/session/session.go b/session/session.go index 35cbe20ac6b46..290b3d6b2f62b 100644 --- a/session/session.go +++ b/session/session.go @@ -1239,6 +1239,7 @@ func (s *session) PrepareStmt(sql string) (stmtID uint32, paramCount int, fields // NewPrepareExec may need startTS to build the executor, for example prepare statement has subquery in int. // So we have to call PrepareTxnCtx here. s.PrepareTxnCtx(ctx) + s.PrepareTxnFuture(ctx) prepareExec := executor.NewPrepareExec(s, executor.GetInfoSchema(s), sql) err = prepareExec.Next(ctx, nil) if err != nil { @@ -1893,8 +1894,6 @@ func (s *session) PrepareTxnCtx(ctx context.Context) { return } - txnFuture := s.getTxnFuture(ctx) - s.txn.changeInvalidToPending(txnFuture) is := domain.GetDomain(s).InfoSchema() s.sessionVars.TxnCtx = &variable.TransactionContext{ InfoSchema: is, @@ -1911,6 +1910,16 @@ func (s *session) PrepareTxnCtx(ctx context.Context) { } } +// PrepareTxnFuture uses to try to get txn future. +func (s *session) PrepareTxnFuture(ctx context.Context) { + if s.txn.validOrPending() { + return + } + + txnFuture := s.getTxnFuture(ctx) + s.txn.changeInvalidToPending(txnFuture) +} + // RefreshTxnCtx implements context.RefreshTxnCtx interface. func (s *session) RefreshTxnCtx(ctx context.Context) error { if err := s.doCommit(ctx); err != nil { diff --git a/sessionctx/context.go b/sessionctx/context.go index 3273ae1d38bf0..9180e0c9c1956 100644 --- a/sessionctx/context.go +++ b/sessionctx/context.go @@ -100,6 +100,8 @@ type Context interface { ReleaseAllTableLocks() // HasLockedTables uses to check whether this session locked any tables. HasLockedTables() bool + // PrepareTxnFuture uses to prepare txn by future. + PrepareTxnFuture(ctx context.Context) } type basicCtxType int diff --git a/util/mock/context.go b/util/mock/context.go index e5dcdc0b5ee6c..2e39eeb67516b 100644 --- a/util/mock/context.go +++ b/util/mock/context.go @@ -251,6 +251,10 @@ func (c *Context) HasLockedTables() bool { return false } +// PrepareTxnFuture implements the sessionctx.Context interface. +func (c *Context) PrepareTxnFuture(ctx context.Context) { +} + // Close implements the sessionctx.Context interface. func (c *Context) Close() { }