@@ -22,8 +22,11 @@ import (
2222 "strconv"
2323 "strings"
2424 "sync"
25+ "time"
2526
2627 "github.com/pingcap/tidb/parser/model"
28+ "github.com/pingcap/tidb/util/logutil"
29+ "go.uber.org/zap"
2730)
2831
2932type runningJobs struct {
@@ -36,6 +39,11 @@ type runningJobs struct {
3639 // It is not necessarily being processed by a worker.
3740 unfinishedIDs map [int64 ]struct {}
3841 unfinishedSchema map [string ]map [string ]struct {} // database -> table -> struct{}
42+
43+ // processingReorgJobID records the ID of the ingest job that is being processed by a worker.
44+ // TODO(tangenta): remove this when we support running multiple concurrent ingest jobs.
45+ processingIngestJobID int64
46+ lastLoggingTime time.Time
3947}
4048
4149func newRunningJobs () * runningJobs {
@@ -46,11 +54,21 @@ func newRunningJobs() *runningJobs {
4654 }
4755}
4856
57+ func (j * runningJobs ) clear () {
58+ j .Lock ()
59+ defer j .Unlock ()
60+ j .unfinishedIDs = make (map [int64 ]struct {})
61+ j .unfinishedSchema = make (map [string ]map [string ]struct {})
62+ }
63+
4964func (j * runningJobs ) add (job * model.Job ) {
5065 j .Lock ()
5166 defer j .Unlock ()
5267 j .processingIDs [job .ID ] = struct {}{}
5368 j .updateInternalRunningJobIDs ()
69+ if isIngestJob (job ) {
70+ j .processingIngestJobID = job .ID
71+ }
5472
5573 if _ , ok := j .unfinishedIDs [job .ID ]; ok {
5674 // Already exists, no need to add it again.
@@ -70,6 +88,9 @@ func (j *runningJobs) remove(job *model.Job) {
7088 defer j .Unlock ()
7189 delete (j .processingIDs , job .ID )
7290 j .updateInternalRunningJobIDs ()
91+ if isIngestJob (job ) && job .ID == j .processingIngestJobID {
92+ j .processingIngestJobID = 0
93+ }
7394
7495 if job .IsFinished () || job .IsSynced () {
7596 delete (j .unfinishedIDs , job .ID )
@@ -110,6 +131,16 @@ func (j *runningJobs) checkRunnable(job *model.Job) bool {
110131 // Already processing by a worker. Skip running it again.
111132 return false
112133 }
134+ if isIngestJob (job ) && j .processingIngestJobID != 0 {
135+ // We only allow one task to use ingest at the same time in order to limit the CPU/memory usage.
136+ if time .Since (j .lastLoggingTime ) > 1 * time .Minute {
137+ logutil .BgLogger ().Info ("ingest backfill worker is already in used by another DDL job" ,
138+ zap .String ("category" , "ddl-ingest" ),
139+ zap .Int64 ("processing job ID" , j .processingIngestJobID ))
140+ j .lastLoggingTime = time .Now ()
141+ }
142+ return false
143+ }
113144 for _ , info := range job .GetInvolvingSchemaInfo () {
114145 if _ , ok := j .unfinishedSchema [model .InvolvingAll ]; ok {
115146 return false
@@ -131,3 +162,9 @@ func (j *runningJobs) checkRunnable(job *model.Job) bool {
131162 }
132163 return true
133164}
165+
166+ func isIngestJob (job * model.Job ) bool {
167+ return (job .Type == model .ActionAddIndex || job .Type == model .ActionAddPrimaryKey ) &&
168+ job .ReorgMeta != nil &&
169+ IsEnableFastReorg ()
170+ }
0 commit comments