From a7881bb71feda8351a17b3ac726f4b8fcda3e760 Mon Sep 17 00:00:00 2001 From: Weizhen Wang Date: Sun, 19 Mar 2023 16:48:56 +0800 Subject: [PATCH] *: data race at the SessionVars.PlanID Signed-off-by: Weizhen Wang --- executor/analyze_col.go | 2 +- executor/prepared.go | 2 +- planner/core/casetest/plan_test.go | 6 +++--- .../tiflash_selection_late_materialization_test.go | 2 +- planner/core/find_best_task.go | 4 ++-- planner/core/initialize.go | 6 ++---- planner/core/optimizer.go | 2 +- planner/core/plan.go | 5 ++--- planner/core/plan_test.go | 8 ++++---- planner/core/point_get_plan.go | 2 +- planner/funcdep/extract_fd_test.go | 6 +++--- planner/optimize.go | 4 ++-- sessionctx/variable/session.go | 5 ++--- 13 files changed, 25 insertions(+), 29 deletions(-) diff --git a/executor/analyze_col.go b/executor/analyze_col.go index 3db5b6dad014b..4679cc4a6f4bc 100644 --- a/executor/analyze_col.go +++ b/executor/analyze_col.go @@ -84,7 +84,7 @@ func (e *AnalyzeColumnsExec) toV2() *AnalyzeColumnsExecV2 { } func (e *AnalyzeColumnsExec) open(ranges []*ranger.Range) error { - e.memTracker = memory.NewTracker(e.ctx.GetSessionVars().PlanID, -1) + e.memTracker = memory.NewTracker(int(e.ctx.GetSessionVars().PlanID.Load()), -1) e.memTracker.AttachTo(e.ctx.GetSessionVars().StmtCtx.MemTracker) e.resultHandler = &tableResultHandler{} firstPartRanges, secondPartRanges := distsql.SplitRangesAcrossInt64Boundary(ranges, true, false, !hasPkHist(e.handleCols)) diff --git a/executor/prepared.go b/executor/prepared.go index df01f21bc2ae2..8a2c000c60c0c 100644 --- a/executor/prepared.go +++ b/executor/prepared.go @@ -125,7 +125,7 @@ func (e *PrepareExec) Next(ctx context.Context, req *chunk.Chunk) error { topsql.AttachAndRegisterSQLInfo(ctx, stmt.NormalizedSQL, stmt.SQLDigest, vars.InRestrictedSQL) } - e.ctx.GetSessionVars().PlanID = 0 + e.ctx.GetSessionVars().PlanID.Store(0) e.ctx.GetSessionVars().PlanColumnID.Store(0) e.ctx.GetSessionVars().MapHashCode2UniqueID4ExtendedCol = nil // In MySQL prepare protocol, the server need to tell the client how many column the prepared statement would return when executing it. diff --git a/planner/core/casetest/plan_test.go b/planner/core/casetest/plan_test.go index 36ff13902bace..3a03e4e881546 100644 --- a/planner/core/casetest/plan_test.go +++ b/planner/core/casetest/plan_test.go @@ -75,7 +75,7 @@ func TestPreferRangeScan(t *testing.T) { } else if i == 1 { tk.MustExec("set session tidb_opt_prefer_range_scan=1") } - tk.Session().GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanID.Store(0) tk.MustExec(tt) info := tk.Session().ShowProcess() require.NotNil(t, info) @@ -126,7 +126,7 @@ func TestNormalizedPlan(t *testing.T) { planNormalizedSuiteData := GetPlanNormalizedSuiteData() planNormalizedSuiteData.LoadTestCases(t, &input, &output) for i, tt := range input { - tk.Session().GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanID.Store(0) tk.MustExec(tt) info := tk.Session().ShowProcess() require.NotNil(t, info) @@ -174,7 +174,7 @@ func TestNormalizedPlanForDiffStore(t *testing.T) { planNormalizedSuiteData.LoadTestCases(t, &input, &output) lastDigest := "" for i, tt := range input { - tk.Session().GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanID.Store(0) tk.MustExec(tt) info := tk.Session().ShowProcess() require.NotNil(t, info) diff --git a/planner/core/casetest/tiflash_selection_late_materialization_test.go b/planner/core/casetest/tiflash_selection_late_materialization_test.go index 87b17a37d90b0..15a61d261e3ec 100644 --- a/planner/core/casetest/tiflash_selection_late_materialization_test.go +++ b/planner/core/casetest/tiflash_selection_late_materialization_test.go @@ -61,7 +61,7 @@ func TestTiFlashLateMaterialization(t *testing.T) { planNormalizedSuiteData := GetPlanNormalizedSuiteData() planNormalizedSuiteData.LoadTestCases(t, &input, &output) for i, tt := range input { - tk.Session().GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanID.Store(0) tk.MustExec(tt) info := tk.Session().ShowProcess() require.NotNil(t, info) diff --git a/planner/core/find_best_task.go b/planner/core/find_best_task.go index 8f092e87e108b..349ff66f39813 100644 --- a/planner/core/find_best_task.go +++ b/planner/core/find_best_task.go @@ -218,7 +218,7 @@ func (p *baseLogicalPlan) enumeratePhysicalPlans4Task(physicalPlans []PhysicalPl // The curCntPlan records the number of possible plans for pp curCntPlan = 1 timeStampNow := p.GetLogicalTS4TaskMap() - savedPlanID := p.ctx.GetSessionVars().PlanID + savedPlanID := p.ctx.GetSessionVars().PlanID.Load() for j, child := range p.children { childProp := pp.GetChildReqProps(j) childTask, cnt, err := child.findBestTask(childProp, &PlanCounterDisabled, opt) @@ -240,7 +240,7 @@ func (p *baseLogicalPlan) enumeratePhysicalPlans4Task(physicalPlans []PhysicalPl // If the target plan can be found in this physicalPlan(pp), rebuild childTasks to build the corresponding combination. if planCounter.IsForce() && int64(*planCounter) <= curCntPlan { - p.ctx.GetSessionVars().PlanID = savedPlanID + p.ctx.GetSessionVars().PlanID.Store(savedPlanID) curCntPlan = int64(*planCounter) err := p.rebuildChildTasks(&childTasks, pp, childCnts, int64(*planCounter), timeStampNow, opt) if err != nil { diff --git a/planner/core/initialize.go b/planner/core/initialize.go index 4a096b7b49204..35ce2f6ad4375 100644 --- a/planner/core/initialize.go +++ b/planner/core/initialize.go @@ -503,9 +503,8 @@ func (p PhysicalIndexJoin) Init(ctx sessionctx.Context, stats *property.StatsInf // Init initializes PhysicalIndexMergeJoin. func (p PhysicalIndexMergeJoin) Init(ctx sessionctx.Context) *PhysicalIndexMergeJoin { - ctx.GetSessionVars().PlanID++ p.tp = plancodec.TypeIndexMergeJoin - p.id = ctx.GetSessionVars().PlanID + p.id = int(ctx.GetSessionVars().PlanID.Add(1)) p.ctx = ctx p.self = &p return &p @@ -513,9 +512,8 @@ func (p PhysicalIndexMergeJoin) Init(ctx sessionctx.Context) *PhysicalIndexMerge // Init initializes PhysicalIndexHashJoin. func (p PhysicalIndexHashJoin) Init(ctx sessionctx.Context) *PhysicalIndexHashJoin { - ctx.GetSessionVars().PlanID++ p.tp = plancodec.TypeIndexHashJoin - p.id = ctx.GetSessionVars().PlanID + p.id = int(ctx.GetSessionVars().PlanID.Add(1)) p.ctx = ctx p.self = &p return &p diff --git a/planner/core/optimizer.go b/planner/core/optimizer.go index 8c33e14fd1e88..69ec42de06308 100644 --- a/planner/core/optimizer.go +++ b/planner/core/optimizer.go @@ -148,7 +148,7 @@ type logicalOptRule interface { // BuildLogicalPlanForTest builds a logical plan for testing purpose from ast.Node. func BuildLogicalPlanForTest(ctx context.Context, sctx sessionctx.Context, node ast.Node, infoSchema infoschema.InfoSchema) (Plan, types.NameSlice, error) { - sctx.GetSessionVars().PlanID = 0 + sctx.GetSessionVars().PlanID.Store(0) sctx.GetSessionVars().PlanColumnID.Store(0) builder, _ := NewPlanBuilder().Init(sctx, infoSchema, &utilhint.BlockHintProcessor{}) p, err := builder.Build(ctx, node) diff --git a/planner/core/plan.go b/planner/core/plan.go index 9ffb859aef769..cf8f609343fd5 100644 --- a/planner/core/plan.go +++ b/planner/core/plan.go @@ -725,11 +725,10 @@ func (p *logicalSchemaProducer) BuildKeyInfo(selfSchema *expression.Schema, chil } func newBasePlan(ctx sessionctx.Context, tp string, offset int) basePlan { - ctx.GetSessionVars().PlanID++ - id := ctx.GetSessionVars().PlanID + id := ctx.GetSessionVars().PlanID.Add(1) return basePlan{ tp: tp, - id: id, + id: int(id), ctx: ctx, blockOffset: offset, } diff --git a/planner/core/plan_test.go b/planner/core/plan_test.go index b79332c146b52..c71b831e0d8fa 100644 --- a/planner/core/plan_test.go +++ b/planner/core/plan_test.go @@ -47,7 +47,7 @@ func TestEncodeDecodePlan(t *testing.T) { tk.MustExec("set tidb_enable_collect_execution_info=1;") tk.MustExec("set tidb_partition_prune_mode='static';") - tk.Session().GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanID.Store(0) getPlanTree := func() (str1, str2 string) { info := tk.Session().ShowProcess() require.NotNil(t, info) @@ -480,7 +480,7 @@ func BenchmarkDecodePlan(b *testing.B) { buf.WriteString(fmt.Sprintf("select count(1) as num,a from t where a='%v' group by a", i)) } query := buf.String() - tk.Session().GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanID.Store(0) tk.MustExec(query) info := tk.Session().ShowProcess() require.NotNil(b, info) @@ -507,7 +507,7 @@ func BenchmarkEncodePlan(b *testing.B) { tk.MustExec("set @@tidb_slow_log_threshold=200000") query := "select count(*) from th t1 join th t2 join th t3 join th t4 join th t5 join th t6 where t1.i=t2.a and t1.i=t3.i and t3.i=t4.i and t4.i=t5.i and t5.i=t6.i" - tk.Session().GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanID.Store(0) tk.MustExec(query) info := tk.Session().ShowProcess() require.NotNil(b, info) @@ -531,7 +531,7 @@ func BenchmarkEncodeFlatPlan(b *testing.B) { tk.MustExec("set @@tidb_slow_log_threshold=200000") query := "select count(*) from th t1 join th t2 join th t3 join th t4 join th t5 join th t6 where t1.i=t2.a and t1.i=t3.i and t3.i=t4.i and t4.i=t5.i and t5.i=t6.i" - tk.Session().GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanID.Store(0) tk.MustExec(query) info := tk.Session().ShowProcess() require.NotNil(b, info) diff --git a/planner/core/point_get_plan.go b/planner/core/point_get_plan.go index 38c05479d8e82..f79de52495f54 100644 --- a/planner/core/point_get_plan.go +++ b/planner/core/point_get_plan.go @@ -534,7 +534,7 @@ func TryFastPlan(ctx sessionctx.Context, node ast.Node) (p Plan) { return nil } - ctx.GetSessionVars().PlanID = 0 + ctx.GetSessionVars().PlanID.Store(0) ctx.GetSessionVars().PlanColumnID.Store(0) switch x := node.(type) { case *ast.SelectStmt: diff --git a/planner/funcdep/extract_fd_test.go b/planner/funcdep/extract_fd_test.go index bc6d6cf77da57..f7656aca0319c 100644 --- a/planner/funcdep/extract_fd_test.go +++ b/planner/funcdep/extract_fd_test.go @@ -217,7 +217,7 @@ func TestFDSet_ExtractFD(t *testing.T) { require.NoError(t, sessiontxn.GetTxnManager(tk.Session()).OnStmtStart(context.TODO(), nil)) stmt, err := par.ParseOneStmt(tt.sql, "", "") require.NoError(t, err, comment) - tk.Session().GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanID.Store(0) tk.Session().GetSessionVars().PlanColumnID.Store(0) err = plannercore.Preprocess(context.Background(), tk.Session(), stmt, plannercore.WithPreprocessorReturn(&plannercore.PreprocessorReturn{InfoSchema: is})) require.NoError(t, err) @@ -316,7 +316,7 @@ func TestFDSet_ExtractFDForApply(t *testing.T) { comment := fmt.Sprintf("case:%v sql:%s", i, tt.sql) stmt, err := par.ParseOneStmt(tt.sql, "", "") require.NoError(t, err, comment) - tk.Session().GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanID.Store(0) tk.Session().GetSessionVars().PlanColumnID.Store(0) err = plannercore.Preprocess(context.Background(), tk.Session(), stmt, plannercore.WithPreprocessorReturn(&plannercore.PreprocessorReturn{InfoSchema: is})) require.NoError(t, err, comment) @@ -364,7 +364,7 @@ func TestFDSet_MakeOuterJoin(t *testing.T) { comment := fmt.Sprintf("case:%v sql:%s", i, tt.sql) stmt, err := par.ParseOneStmt(tt.sql, "", "") require.NoError(t, err, comment) - tk.Session().GetSessionVars().PlanID = 0 + tk.Session().GetSessionVars().PlanID.Store(0) tk.Session().GetSessionVars().PlanColumnID.Store(0) err = plannercore.Preprocess(context.Background(), tk.Session(), stmt, plannercore.WithPreprocessorReturn(&plannercore.PreprocessorReturn{InfoSchema: is})) require.NoError(t, err, comment) diff --git a/planner/optimize.go b/planner/optimize.go index 12cdcbac45642..3410c1f56d1d1 100644 --- a/planner/optimize.go +++ b/planner/optimize.go @@ -492,12 +492,12 @@ func OptimizeExecStmt(ctx context.Context, sctx sessionctx.Context, } func buildLogicalPlan(ctx context.Context, sctx sessionctx.Context, node ast.Node, builder *core.PlanBuilder) (core.Plan, error) { - sctx.GetSessionVars().PlanID = 0 + sctx.GetSessionVars().PlanID.Store(0) sctx.GetSessionVars().PlanColumnID.Store(0) sctx.GetSessionVars().MapHashCode2UniqueID4ExtendedCol = nil failpoint.Inject("mockRandomPlanID", func() { - sctx.GetSessionVars().PlanID = rand.Intn(1000) // nolint:gosec + sctx.GetSessionVars().PlanID.Store(rand.Int31n(1000)) // nolint:gosec }) // reset fields about rewrite diff --git a/sessionctx/variable/session.go b/sessionctx/variable/session.go index 2739cde305be3..5ec0e1f9dbfe8 100644 --- a/sessionctx/variable/session.go +++ b/sessionctx/variable/session.go @@ -699,7 +699,7 @@ type SessionVars struct { ConnectionID uint64 // PlanID is the unique id of logical and physical plan. - PlanID int + PlanID atomic.Int32 // PlanColumnID is the unique id for column when building plan. PlanColumnID atomic.Int64 @@ -1603,8 +1603,7 @@ func (s *SessionVars) BuildParserConfig() parser.ParserConfig { // AllocNewPlanID alloc new ID func (s *SessionVars) AllocNewPlanID() int { - s.PlanID++ - return s.PlanID + return int(s.PlanID.Add(1)) } const (