Skip to content

Commit

Permalink
This is an automated cherry-pick of #40280
Browse files Browse the repository at this point in the history
Signed-off-by: ti-chi-bot <ti-community-prow-bot@tidb.io>
  • Loading branch information
qw4990 authored and ti-chi-bot committed Feb 14, 2023
1 parent e826aa7 commit 3c6c788
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 1 deletion.
34 changes: 33 additions & 1 deletion planner/core/plan_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,24 @@ func GetPlanFromSessionPlanCache(ctx context.Context, sctx sessionctx.Context,
stmtCtx.UseCache = stmtAst.UseCache

var bindSQL string
var ignorePlanCache = false
if stmtCtx.UseCache {
var ignoreByBinding bool
bindSQL, ignoreByBinding = GetBindSQL4PlanCache(sctx, stmt)
if ignoreByBinding {
stmtCtx.SetSkipPlanCache(errors.Errorf("skip plan-cache: ignore plan cache by binding"))
}
}

// In rc or for update read, we need the latest schema version to decide whether we need to
// rebuild the plan. So we set this value in rc or for update read. In other cases, let it be 0.
var latestSchemaVersion int64

<<<<<<< HEAD
if stmtAst.UseCache {
bindSQL, ignorePlanCache = GetBindSQL4PlanCache(sctx, stmt)
=======
if stmtCtx.UseCache {
>>>>>>> 7fafb6db45 (planner: better coordination between the ignore_plan_cache() binding and plan-cache (#40280))
if sctx.GetSessionVars().IsIsolation(ast.ReadCommitted) || stmt.ForUpdateRead {
// In Rc or ForUpdateRead, we should check if the information schema has been changed since
// last time. If it changed, we should rebuild the plan. Here, we use a different and more
Expand All @@ -148,21 +158,35 @@ func GetPlanFromSessionPlanCache(ctx context.Context, sctx sessionctx.Context,

paramNum, paramTypes := parseParamTypes(sctx, params)

<<<<<<< HEAD
if stmtAst.UseCache && stmtAst.CachedPlan != nil && !ignorePlanCache { // for point query plan
if plan, names, ok, err := getPointQueryPlan(stmtAst, sessVars, stmtCtx); ok {
=======
if stmtCtx.UseCache && stmtAst.CachedPlan != nil { // for point query plan
if plan, names, ok, err := getCachedPointPlan(stmtAst, sessVars, stmtCtx); ok {
>>>>>>> 7fafb6db45 (planner: better coordination between the ignore_plan_cache() binding and plan-cache (#40280))
return plan, names, err
}
}

<<<<<<< HEAD
if stmtAst.UseCache && !ignorePlanCache { // for general plans
if plan, names, ok, err := getGeneralPlan(sctx, isGeneralPlanCache, cacheKey, bindSQL, is, stmt,
=======
if stmtCtx.UseCache { // for non-point plans
if plan, names, ok, err := getCachedPlan(sctx, isNonPrepared, cacheKey, bindSQL, is, stmt,
>>>>>>> 7fafb6db45 (planner: better coordination between the ignore_plan_cache() binding and plan-cache (#40280))
paramTypes); err != nil || ok {
return plan, names, err
}
}

<<<<<<< HEAD
return generateNewPlan(ctx, sctx, isGeneralPlanCache, is, stmt, ignorePlanCache, cacheKey,
latestSchemaVersion, paramNum, paramTypes, bindSQL)
=======
return generateNewPlan(ctx, sctx, isNonPrepared, is, stmt, cacheKey, latestSchemaVersion, paramNum, paramTypes, bindSQL)
>>>>>>> 7fafb6db45 (planner: better coordination between the ignore_plan_cache() binding and plan-cache (#40280))
}

// parseParamTypes get parameters' types in PREPARE statement
Expand Down Expand Up @@ -253,8 +277,12 @@ func getGeneralPlan(sctx sessionctx.Context, isGeneralPlanCache bool, cacheKey k

// generateNewPlan call the optimizer to generate a new plan for current statement
// and try to add it to cache
<<<<<<< HEAD
func generateNewPlan(ctx context.Context, sctx sessionctx.Context, isGeneralPlanCache bool, is infoschema.InfoSchema, stmt *PlanCacheStmt,
ignorePlanCache bool, cacheKey kvcache.Key, latestSchemaVersion int64, paramNum int,
=======
func generateNewPlan(ctx context.Context, sctx sessionctx.Context, isNonPrepared bool, is infoschema.InfoSchema, stmt *PlanCacheStmt, cacheKey kvcache.Key, latestSchemaVersion int64, paramNum int,
>>>>>>> 7fafb6db45 (planner: better coordination between the ignore_plan_cache() binding and plan-cache (#40280))
paramTypes []*types.FieldType, bindSQL string) (Plan, []*types.FieldName, error) {
stmtAst := stmt.PreparedAst
sessVars := sctx.GetSessionVars()
Expand All @@ -276,7 +304,11 @@ func generateNewPlan(ctx context.Context, sctx sessionctx.Context, isGeneralPlan
if containTableDual(p) && paramNum > 0 {
stmtCtx.SkipPlanCache = true
}
<<<<<<< HEAD
if stmtAst.UseCache && !stmtCtx.SkipPlanCache && !ignorePlanCache {
=======
if stmtCtx.UseCache {
>>>>>>> 7fafb6db45 (planner: better coordination between the ignore_plan_cache() binding and plan-cache (#40280))
// rebuild key to exclude kv.TiFlash when stmt is not read only
if _, isolationReadContainTiFlash := sessVars.IsolationReadEngines[kv.TiFlash]; isolationReadContainTiFlash && !IsReadOnly(stmtAst.Stmt, sessVars) {
delete(sessVars.IsolationReadEngines, kv.TiFlash)
Expand Down
45 changes: 45 additions & 0 deletions planner/core/plan_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,48 @@ func TestPlanCacheDiagInfo(t *testing.T) {
tk.MustExec("execute stmt using @a, @b") // a=1 and a=1 -> a=1
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 skip plan-cache: some parameters may be overwritten"))
}
<<<<<<< HEAD
=======

func TestIssue40225(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t (a int, key(a))")
tk.MustExec("prepare st from 'select * from t where a<?'")
tk.MustExec("set @a='1'")
tk.MustExec("execute st using @a")
tk.MustQuery("show warnings").Sort().Check(testkit.Rows("Warning 1105 skip plan-cache: '1' may be converted to INT")) // plan-cache limitation
tk.MustExec("create binding for select * from t where a<1 using select /*+ ignore_plan_cache() */ * from t where a<1")
tk.MustExec("execute st using @a")
tk.MustQuery("show warnings").Sort().Check(testkit.Rows("Warning 1105 skip plan-cache: ignore plan cache by binding"))
// no warning about plan-cache limitations('1' -> INT) since plan-cache is totally disabled.

tk.MustExec("prepare st from 'select * from t where a>?'")
tk.MustExec("set @a=1")
tk.MustExec("execute st using @a")
tk.MustExec("execute st using @a")
tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1"))
tk.MustExec("create binding for select * from t where a>1 using select /*+ ignore_plan_cache() */ * from t where a>1")
tk.MustExec("execute st using @a")
tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0"))
tk.MustExec("execute st using @a")
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1"))
}

func TestUncacheableReason(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t (a int)")

tk.MustExec("prepare st from 'select * from t limit ?'")
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 skip plan-cache: query has 'limit ?' is un-cacheable"))

tk.MustExec("set @a=1")
tk.MustQuery("execute st using @a").Check(testkit.Rows())
tk.MustExec("prepare st from 'select * from t limit ?'")
// show the corresponding un-cacheable reason at execute-stage as well
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 skip plan-cache: query has 'limit ?' is un-cacheable"))
}
>>>>>>> 7fafb6db45 (planner: better coordination between the ignore_plan_cache() binding and plan-cache (#40280))

0 comments on commit 3c6c788

Please sign in to comment.