@@ -22,8 +22,11 @@ import (
22
22
"strconv"
23
23
"strings"
24
24
"sync"
25
+ "time"
25
26
26
27
"github.com/pingcap/tidb/pkg/parser/model"
28
+ "github.com/pingcap/tidb/pkg/util/logutil"
29
+ "go.uber.org/zap"
27
30
)
28
31
29
32
type runningJobs struct {
@@ -36,6 +39,11 @@ type runningJobs struct {
36
39
// It is not necessarily being processed by a worker.
37
40
unfinishedIDs map [int64 ]struct {}
38
41
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
39
47
}
40
48
41
49
func newRunningJobs () * runningJobs {
@@ -47,6 +55,8 @@ func newRunningJobs() *runningJobs {
47
55
}
48
56
49
57
func (j * runningJobs ) clear () {
58
+ j .Lock ()
59
+ defer j .Unlock ()
50
60
j .unfinishedIDs = make (map [int64 ]struct {})
51
61
j .unfinishedSchema = make (map [string ]map [string ]struct {})
52
62
}
@@ -56,6 +66,9 @@ func (j *runningJobs) add(job *model.Job) {
56
66
defer j .Unlock ()
57
67
j .processingIDs [job .ID ] = struct {}{}
58
68
j .updateInternalRunningJobIDs ()
69
+ if isIngestJob (job ) {
70
+ j .processingIngestJobID = job .ID
71
+ }
59
72
60
73
if _ , ok := j .unfinishedIDs [job .ID ]; ok {
61
74
// Already exists, no need to add it again.
@@ -75,6 +88,9 @@ func (j *runningJobs) remove(job *model.Job) {
75
88
defer j .Unlock ()
76
89
delete (j .processingIDs , job .ID )
77
90
j .updateInternalRunningJobIDs ()
91
+ if isIngestJob (job ) && job .ID == j .processingIngestJobID {
92
+ j .processingIngestJobID = 0
93
+ }
78
94
79
95
if job .IsFinished () || job .IsSynced () {
80
96
delete (j .unfinishedIDs , job .ID )
@@ -115,6 +131,16 @@ func (j *runningJobs) checkRunnable(job *model.Job) bool {
115
131
// Already processing by a worker. Skip running it again.
116
132
return false
117
133
}
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
+ }
118
144
for _ , info := range job .GetInvolvingSchemaInfo () {
119
145
if _ , ok := j .unfinishedSchema [model .InvolvingAll ]; ok {
120
146
return false
@@ -136,3 +162,9 @@ func (j *runningJobs) checkRunnable(job *model.Job) bool {
136
162
}
137
163
return true
138
164
}
165
+
166
+ func isIngestJob (job * model.Job ) bool {
167
+ return (job .Type == model .ActionAddIndex || job .Type == model .ActionAddPrimaryKey ) &&
168
+ job .ReorgMeta != nil &&
169
+ job .ReorgMeta .IsFastReorg
170
+ }
0 commit comments