Skip to content

Commit

Permalink
variable: unifiy MaxExecuteTime usage and fix some problem (#50915) (#…
Browse files Browse the repository at this point in the history
…52619)

close #50872, close #50914
  • Loading branch information
ti-chi-bot authored May 28, 2024
1 parent 5a66534 commit 62e0c8d
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 25 deletions.
12 changes: 2 additions & 10 deletions pkg/executor/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ func (a *ExecStmt) PointGet(ctx context.Context) (*recordSet, error) {
if raw, ok := sctx.(processinfoSetter); ok {
pi = raw
sql := a.OriginText()
maxExecutionTime := getMaxExecutionTime(sctx)
maxExecutionTime := sctx.GetSessionVars().GetMaxExecutionTime()
// Update processinfo, ShowProcess() will use it.
pi.SetProcessInfo(sql, time.Now(), cmd, maxExecutionTime)
if sctx.GetSessionVars().StmtCtx.StmtType == "" {
Expand Down Expand Up @@ -553,7 +553,7 @@ func (a *ExecStmt) Exec(ctx context.Context) (_ sqlexec.RecordSet, err error) {
if raw, ok := sctx.(processinfoSetter); ok {
pi = raw
sql := a.getSQLForProcessInfo()
maxExecutionTime := getMaxExecutionTime(sctx)
maxExecutionTime := sctx.GetSessionVars().GetMaxExecutionTime()
// Update processinfo, ShowProcess() will use it.
if a.Ctx.GetSessionVars().StmtCtx.StmtType == "" {
a.Ctx.GetSessionVars().StmtCtx.StmtType = ast.GetStmtLabel(a.StmtNode)
Expand Down Expand Up @@ -826,14 +826,6 @@ func isNoResultPlan(p plannercore.Plan) bool {
return false
}

// getMaxExecutionTime get the max execution timeout value.
func getMaxExecutionTime(sctx sessionctx.Context) uint64 {
if sctx.GetSessionVars().StmtCtx.HasMaxExecutionTime {
return sctx.GetSessionVars().StmtCtx.MaxExecutionTime
}
return sctx.GetSessionVars().MaxExecutionTime
}

type chunkRowRecordSet struct {
rows []chunk.Row
idx int
Expand Down
7 changes: 6 additions & 1 deletion pkg/planner/core/casetest/planstats/plan_stats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ func TestPlanStatsLoadTimeout(t *testing.T) {
ToTimeout: time.Now().Local().Add(timeout),
}
dom.StatsHandle().AppendNeededItem(task, timeout) // make channel queue full
sql := "select * from t where c>1"
sql := "select /*+ MAX_EXECUTION_TIME(1000) */ * from t where c>1"
stmt, err := p.ParseOneStmt(sql, "", "")
require.NoError(t, err)
tk.MustExec("set global tidb_stats_load_pseudo_timeout=false")
Expand All @@ -286,6 +286,11 @@ func TestPlanStatsLoadTimeout(t *testing.T) {
tk.MustExec(sql) // not fail sql for timeout when pseudo=true
require.NoError(t, failpoint.Disable("github.com/pingcap/executor/assertSyncStatsFailed"))

// Test Issue #50872.
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/pkg/planner/core/assertSyncWaitFailed", `return(true)`))
tk.MustExec(sql)
failpoint.Disable("github.com/pingcap/tidb/pkg/planner/core/assertSyncWaitFailed")

plan, _, err := planner.Optimize(context.TODO(), ctx, stmt, is)
require.NoError(t, err) // not fail sql for timeout when pseudo=true
switch pp := plan.(type) {
Expand Down
28 changes: 14 additions & 14 deletions pkg/planner/core/plan_stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"context"
"time"

"github.com/pingcap/failpoint"
"github.com/pingcap/tidb/pkg/domain"
"github.com/pingcap/tidb/pkg/infoschema"
"github.com/pingcap/tidb/pkg/parser/model"
Expand All @@ -28,7 +29,6 @@ import (
"github.com/pingcap/tidb/pkg/statistics"
"github.com/pingcap/tidb/pkg/table"
"github.com/pingcap/tidb/pkg/util/logutil"
"github.com/pingcap/tidb/pkg/util/mathutil"
"go.uber.org/zap"
)

Expand All @@ -40,7 +40,7 @@ func (collectPredicateColumnsPoint) optimize(_ context.Context, plan LogicalPlan
return plan, planChanged, nil
}
predicateNeeded := variable.EnableColumnTracking.Load()
syncWait := plan.SCtx().GetSessionVars().StatsLoadSyncWait.Load() * time.Millisecond.Nanoseconds()
syncWait := plan.SCtx().GetSessionVars().StatsLoadSyncWait.Load()
histNeeded := syncWait > 0
predicateColumns, histNeededColumns, visitedPhysTblIDs := CollectColumnStatsUsage(plan, predicateNeeded, histNeeded)
if len(predicateColumns) > 0 {
Expand Down Expand Up @@ -157,21 +157,21 @@ func (syncWaitStatsLoadPoint) name() string {
return "sync_wait_stats_load_point"
}

const maxDuration = 1<<63 - 1

// RequestLoadStats send load column/index stats requests to stats handle
func RequestLoadStats(ctx sessionctx.Context, neededHistItems []model.TableItemID, syncWait int64) error {
stmtCtx := ctx.GetSessionVars().StmtCtx
hintMaxExecutionTime := int64(stmtCtx.MaxExecutionTime)
if hintMaxExecutionTime <= 0 {
hintMaxExecutionTime = maxDuration
maxExecutionTime := ctx.GetSessionVars().GetMaxExecutionTime()
if maxExecutionTime > 0 && maxExecutionTime < uint64(syncWait) {
syncWait = int64(maxExecutionTime)
}
sessMaxExecutionTime := int64(ctx.GetSessionVars().MaxExecutionTime)
if sessMaxExecutionTime <= 0 {
sessMaxExecutionTime = maxDuration
}
waitTime := mathutil.Min(syncWait, hintMaxExecutionTime, sessMaxExecutionTime)
var timeout = time.Duration(waitTime)
failpoint.Inject("assertSyncWaitFailed", func(val failpoint.Value) {
if val.(bool) {
if syncWait != 1 {
panic("syncWait should be 1(ms)")
}
}
})
var timeout = time.Duration(syncWait * time.Millisecond.Nanoseconds())
stmtCtx := ctx.GetSessionVars().StmtCtx
err := domain.GetDomain(ctx).StatsHandle().SendLoadRequests(stmtCtx, neededHistItems, timeout)
if err != nil {
stmtCtx.IsSyncStatsFailed = true
Expand Down
4 changes: 4 additions & 0 deletions pkg/session/test/variable/variable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ func TestMaxExecutionTime(t *testing.T) {
require.EqualError(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings()[0].Err, "MAX_EXECUTION_TIME() is defined more than once, only the last definition takes effect: MAX_EXECUTION_TIME(500)")
require.True(t, tk.Session().GetSessionVars().StmtCtx.HasMaxExecutionTime)
require.Equal(t, uint64(500), tk.Session().GetSessionVars().StmtCtx.MaxExecutionTime)
require.Equal(t, uint64(500), tk.Session().GetSessionVars().GetMaxExecutionTime())

tk.MustQuery("select @@MAX_EXECUTION_TIME;").Check(testkit.Rows("0"))
tk.MustQuery("select @@global.MAX_EXECUTION_TIME;").Check(testkit.Rows("0"))
Expand All @@ -328,6 +329,9 @@ func TestMaxExecutionTime(t *testing.T) {

tk.MustExec("set @@MAX_EXECUTION_TIME = 150;")
tk.MustQuery("select * FROM MaxExecTime;")
require.Equal(t, uint64(150), tk.Session().GetSessionVars().GetMaxExecutionTime())
tk.MustQuery("select /*+ MAX_EXECUTION_TIME(1000) */ * FROM MaxExecTime;")
require.Equal(t, uint64(1000), tk.Session().GetSessionVars().GetMaxExecutionTime())

tk.MustQuery("select @@global.MAX_EXECUTION_TIME;").Check(testkit.Rows("300"))
tk.MustQuery("select @@MAX_EXECUTION_TIME;").Check(testkit.Rows("150"))
Expand Down
1 change: 1 addition & 0 deletions pkg/session/test/vars/vars_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ func TestGlobalVarAccessor(t *testing.T) {
tk2 := testkit.NewTestKit(t, store)
tk2.MustExec("use test")
require.Equal(t, uint64(100), tk2.Session().GetSessionVars().MaxExecutionTime)
require.Equal(t, uint64(100), tk2.Session().GetSessionVars().GetMaxExecutionTime())
tk1.MustExec("set @@global.max_execution_time = 0")

result := tk.MustQuery("show global variables where variable_name='sql_select_limit';")
Expand Down
8 changes: 8 additions & 0 deletions pkg/sessionctx/variable/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -3568,6 +3568,14 @@ func (s *SessionVars) GetRuntimeFilterMode() RuntimeFilterMode {
return s.runtimeFilterMode
}

// GetMaxExecutionTime get the max execution timeout value.
func (s *SessionVars) GetMaxExecutionTime() uint64 {
if s.StmtCtx.HasMaxExecutionTime {
return s.StmtCtx.MaxExecutionTime
}
return s.MaxExecutionTime
}

// GetTiKVClientReadTimeout returns readonly kv request timeout, prefer query hint over session variable
func (s *SessionVars) GetTiKVClientReadTimeout() uint64 {
return s.TiKVClientReadTimeout
Expand Down

0 comments on commit 62e0c8d

Please sign in to comment.