@@ -215,6 +215,7 @@ type Domain struct {
215
215
216
216
instancePlanCache sessionctx.InstancePlanCache // the instance level plan cache
217
217
218
+ statsOwner owner.Manager
218
219
// deferFn is used to release infoschema object lazily during v1 and v2 switch
219
220
deferFn
220
221
}
@@ -2313,20 +2314,22 @@ func (do *Domain) UpdateTableStatsLoop(ctx, initStatsCtx sessionctx.Context) err
2313
2314
if do .statsLease >= 0 {
2314
2315
do .wg .Run (do .loadStatsWorker , "loadStatsWorker" )
2315
2316
}
2316
- owner := do .newOwnerManager (handle .StatsPrompt , handle .StatsOwnerKey )
2317
+ variable .EnableStatsOwner = do .enableStatsOwner
2318
+ variable .DisableStatsOwner = do .disableStatsOwner
2319
+ do .statsOwner = do .newOwnerManager (handle .StatsPrompt , handle .StatsOwnerKey )
2317
2320
do .wg .Run (func () {
2318
2321
do .indexUsageWorker ()
2319
2322
}, "indexUsageWorker" )
2320
2323
if do .statsLease <= 0 {
2321
2324
// For statsLease > 0, `updateStatsWorker` handles the quit of stats owner.
2322
- do .wg .Run (func () { quitStatsOwner (do , owner ) }, "quitStatsOwner" )
2325
+ do .wg .Run (func () { quitStatsOwner (do , do . statsOwner ) }, "quitStatsOwner" )
2323
2326
return nil
2324
2327
}
2325
2328
do .SetStatsUpdating (true )
2326
2329
// The stats updated worker doesn't require the stats initialization to be completed.
2327
2330
// This is because the updated worker's primary responsibilities are to update the change delta and handle DDL operations.
2328
2331
// These tasks do not interfere with or depend on the initialization process.
2329
- do .wg .Run (func () { do .updateStatsWorker (ctx , owner ) }, "updateStatsWorker" )
2332
+ do .wg .Run (func () { do .updateStatsWorker (ctx ) }, "updateStatsWorker" )
2330
2333
do .wg .Run (func () {
2331
2334
do .handleDDLEvent ()
2332
2335
}, "handleDDLEvent" )
@@ -2339,7 +2342,7 @@ func (do *Domain) UpdateTableStatsLoop(ctx, initStatsCtx sessionctx.Context) err
2339
2342
case <- do .exit : // It may happen that before initStatsDone, tidb receive Ctrl+C
2340
2343
return
2341
2344
}
2342
- do .autoAnalyzeWorker (owner )
2345
+ do .autoAnalyzeWorker ()
2343
2346
},
2344
2347
"autoAnalyzeWorker" ,
2345
2348
)
@@ -2350,7 +2353,7 @@ func (do *Domain) UpdateTableStatsLoop(ctx, initStatsCtx sessionctx.Context) err
2350
2353
case <- do .exit : // It may happen that before initStatsDone, tidb receive Ctrl+C
2351
2354
return
2352
2355
}
2353
- do .analyzeJobsCleanupWorker (owner )
2356
+ do .analyzeJobsCleanupWorker ()
2354
2357
},
2355
2358
"analyzeJobsCleanupWorker" ,
2356
2359
)
@@ -2380,6 +2383,25 @@ func (do *Domain) UpdateTableStatsLoop(ctx, initStatsCtx sessionctx.Context) err
2380
2383
return nil
2381
2384
}
2382
2385
2386
+ // enableStatsOwner enables this node to execute stats owner jobs.
2387
+ // Since ownerManager.CampaignOwner will start a new goroutine to run ownerManager.campaignLoop,
2388
+ // we should make sure that before invoking enableStatsOwner(), stats owner is DISABLE.
2389
+ func (do * Domain ) enableStatsOwner () error {
2390
+ if ! do .statsOwner .IsOwner () {
2391
+ err := do .statsOwner .CampaignOwner ()
2392
+ return errors .Trace (err )
2393
+ }
2394
+ return nil
2395
+ }
2396
+
2397
+ // disableStatsOwner disable this node to execute stats owner.
2398
+ // We should make sure that before invoking disableStatsOwner(), stats owner is ENABLE.
2399
+ func (do * Domain ) disableStatsOwner () error {
2400
+ // disable campaign by interrupting campaignLoop
2401
+ do .statsOwner .CampaignCancel ()
2402
+ return nil
2403
+ }
2404
+
2383
2405
func quitStatsOwner (do * Domain , mgr owner.Manager ) {
2384
2406
<- do .exit
2385
2407
mgr .Cancel ()
@@ -2404,9 +2426,11 @@ func (do *Domain) newOwnerManager(prompt, ownerKey string) owner.Manager {
2404
2426
statsOwner = owner .NewOwnerManager (context .Background (), do .etcdClient , prompt , id , ownerKey )
2405
2427
}
2406
2428
// TODO: Need to do something when err is not nil.
2407
- err := statsOwner .CampaignOwner ()
2408
- if err != nil {
2409
- logutil .BgLogger ().Warn ("campaign owner failed" , zap .Error (err ))
2429
+ if ownerKey == handle .StatsOwnerKey && config .GetGlobalConfig ().Instance .TiDBEnableStatsOwner .Load () {
2430
+ err := statsOwner .CampaignOwner ()
2431
+ if err != nil {
2432
+ logutil .BgLogger ().Warn ("campaign owner failed" , zap .Error (err ))
2433
+ }
2410
2434
}
2411
2435
return statsOwner
2412
2436
}
@@ -2493,15 +2517,15 @@ func (do *Domain) indexUsageWorker() {
2493
2517
}
2494
2518
}
2495
2519
2496
- func (* Domain ) updateStatsWorkerExitPreprocessing (statsHandle * handle.Handle , owner owner. Manager ) {
2520
+ func (do * Domain ) updateStatsWorkerExitPreprocessing (statsHandle * handle.Handle ) {
2497
2521
ch := make (chan struct {}, 1 )
2498
2522
timeout , cancel := context .WithTimeout (context .Background (), 10 * time .Second )
2499
2523
defer cancel ()
2500
2524
go func () {
2501
2525
logutil .BgLogger ().Info ("updateStatsWorker is going to exit, start to flush stats" )
2502
2526
statsHandle .FlushStats ()
2503
2527
logutil .BgLogger ().Info ("updateStatsWorker ready to release owner" )
2504
- owner .Cancel ()
2528
+ do . statsOwner .Cancel ()
2505
2529
ch <- struct {}{}
2506
2530
}()
2507
2531
select {
@@ -2532,7 +2556,7 @@ func (do *Domain) handleDDLEvent() {
2532
2556
}
2533
2557
}
2534
2558
2535
- func (do * Domain ) updateStatsWorker (_ sessionctx.Context , owner owner. Manager ) {
2559
+ func (do * Domain ) updateStatsWorker (_ sessionctx.Context ) {
2536
2560
defer util .Recover (metrics .LabelDomain , "updateStatsWorker" , nil , false )
2537
2561
logutil .BgLogger ().Info ("updateStatsWorker started." )
2538
2562
lease := do .statsLease
@@ -2558,15 +2582,15 @@ func (do *Domain) updateStatsWorker(_ sessionctx.Context, owner owner.Manager) {
2558
2582
for {
2559
2583
select {
2560
2584
case <- do .exit :
2561
- do .updateStatsWorkerExitPreprocessing (statsHandle , owner )
2585
+ do .updateStatsWorkerExitPreprocessing (statsHandle )
2562
2586
return
2563
2587
case <- deltaUpdateTicker .C :
2564
2588
err := statsHandle .DumpStatsDeltaToKV (false )
2565
2589
if err != nil {
2566
2590
logutil .BgLogger ().Debug ("dump stats delta failed" , zap .Error (err ))
2567
2591
}
2568
2592
case <- gcStatsTicker .C :
2569
- if ! owner .IsOwner () {
2593
+ if ! do . statsOwner .IsOwner () {
2570
2594
continue
2571
2595
}
2572
2596
err := statsHandle .GCStats (do .InfoSchema (), do .GetSchemaLease ())
@@ -2587,7 +2611,7 @@ func (do *Domain) updateStatsWorker(_ sessionctx.Context, owner owner.Manager) {
2587
2611
}
2588
2612
}
2589
2613
2590
- func (do * Domain ) autoAnalyzeWorker (owner owner. Manager ) {
2614
+ func (do * Domain ) autoAnalyzeWorker () {
2591
2615
defer util .Recover (metrics .LabelDomain , "autoAnalyzeWorker" , nil , false )
2592
2616
statsHandle := do .StatsHandle ()
2593
2617
analyzeTicker := time .NewTicker (do .statsLease )
@@ -2598,7 +2622,7 @@ func (do *Domain) autoAnalyzeWorker(owner owner.Manager) {
2598
2622
for {
2599
2623
select {
2600
2624
case <- analyzeTicker .C :
2601
- if variable .RunAutoAnalyze .Load () && ! do .stopAutoAnalyze .Load () && owner .IsOwner () {
2625
+ if variable .RunAutoAnalyze .Load () && ! do .stopAutoAnalyze .Load () && do . statsOwner .IsOwner () {
2602
2626
statsHandle .HandleAutoAnalyze ()
2603
2627
}
2604
2628
case <- do .exit :
@@ -2621,7 +2645,7 @@ func (do *Domain) autoAnalyzeWorker(owner owner.Manager) {
2621
2645
// It first retrieves the list of current analyze processes, then removes any analyze job
2622
2646
// that is not associated with a current process. Additionally, if the current instance is the owner,
2623
2647
// it also cleans up corrupted analyze jobs on dead instances.
2624
- func (do * Domain ) analyzeJobsCleanupWorker (owner owner. Manager ) {
2648
+ func (do * Domain ) analyzeJobsCleanupWorker () {
2625
2649
defer util .Recover (metrics .LabelDomain , "analyzeJobsCleanupWorker" , nil , false )
2626
2650
// For GC.
2627
2651
const gcInterval = time .Hour
@@ -2642,7 +2666,7 @@ func (do *Domain) analyzeJobsCleanupWorker(owner owner.Manager) {
2642
2666
select {
2643
2667
case <- gcTicker .C :
2644
2668
// Only the owner should perform this operation.
2645
- if owner .IsOwner () {
2669
+ if do . statsOwner .IsOwner () {
2646
2670
updateTime := time .Now ().AddDate (0 , 0 , - daysToKeep )
2647
2671
err := statsHandle .DeleteAnalyzeJobs (updateTime )
2648
2672
if err != nil {
@@ -2666,7 +2690,7 @@ func (do *Domain) analyzeJobsCleanupWorker(owner owner.Manager) {
2666
2690
logutil .BgLogger ().Warn ("cleanup analyze jobs on current instance failed" , zap .Error (err ))
2667
2691
}
2668
2692
2669
- if owner .IsOwner () {
2693
+ if do . statsOwner .IsOwner () {
2670
2694
err = statsHandle .CleanupCorruptedAnalyzeJobsOnDeadInstances ()
2671
2695
if err != nil {
2672
2696
logutil .BgLogger ().Warn ("cleanup analyze jobs on dead instances failed" , zap .Error (err ))
0 commit comments