@@ -22,8 +22,11 @@ import (
22
22
"strconv"
23
23
"strings"
24
24
"sync"
25
+ "time"
25
26
26
27
"github.com/pingcap/tidb/parser/model"
28
+ "github.com/pingcap/tidb/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 {
@@ -46,11 +54,21 @@ func newRunningJobs() *runningJobs {
46
54
}
47
55
}
48
56
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
+
49
64
func (j * runningJobs ) add (job * model.Job ) {
50
65
j .Lock ()
51
66
defer j .Unlock ()
52
67
j .processingIDs [job .ID ] = struct {}{}
53
68
j .updateInternalRunningJobIDs ()
69
+ if isIngestJob (job ) {
70
+ j .processingIngestJobID = job .ID
71
+ }
54
72
55
73
if _ , ok := j .unfinishedIDs [job .ID ]; ok {
56
74
// Already exists, no need to add it again.
@@ -70,6 +88,9 @@ func (j *runningJobs) remove(job *model.Job) {
70
88
defer j .Unlock ()
71
89
delete (j .processingIDs , job .ID )
72
90
j .updateInternalRunningJobIDs ()
91
+ if isIngestJob (job ) && job .ID == j .processingIngestJobID {
92
+ j .processingIngestJobID = 0
93
+ }
73
94
74
95
if job .IsFinished () || job .IsSynced () {
75
96
delete (j .unfinishedIDs , job .ID )
@@ -110,6 +131,16 @@ func (j *runningJobs) checkRunnable(job *model.Job) bool {
110
131
// Already processing by a worker. Skip running it again.
111
132
return false
112
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
+ }
113
144
for _ , info := range job .GetInvolvingSchemaInfo () {
114
145
if _ , ok := j .unfinishedSchema [model .InvolvingAll ]; ok {
115
146
return false
@@ -131,3 +162,9 @@ func (j *runningJobs) checkRunnable(job *model.Job) bool {
131
162
}
132
163
return true
133
164
}
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