@@ -128,6 +128,10 @@ type jobScheduler struct {
128
128
runningJobs * runningJobs
129
129
sysTblMgr systable.Manager
130
130
schemaLoader SchemaLoader
131
+ // currMinJobID is the minimal job ID in tidb_ddl_job table, we use it to mitigate
132
+ // this issue https://github.com/pingcap/tidb/issues/52905
133
+ currMinJobID int64
134
+ lastRefreshMinIDTime time.Time
131
135
132
136
// those fields are created on start
133
137
reorgWorkerPool * workerPool
@@ -191,14 +195,15 @@ func (s *jobScheduler) getJob(se *sess.Session, tp jobType) (*model.Job, error)
191
195
not = ""
192
196
label = "get_job_reorg"
193
197
}
198
+ // TODO replace this sub-query with memory implementation.
194
199
const getJobSQL = `select job_meta, processing from mysql.tidb_ddl_job where job_id in
195
- (select min(job_id) from mysql.tidb_ddl_job group by schema_ids, table_ids, processing)
200
+ (select min(job_id) from mysql.tidb_ddl_job where job_id >= %d group by schema_ids, table_ids, processing)
196
201
and %s reorg %s order by processing desc, job_id`
197
202
var excludedJobIDs string
198
203
if ids := s .runningJobs .allIDs (); len (ids ) > 0 {
199
204
excludedJobIDs = fmt .Sprintf ("and job_id not in (%s)" , ids )
200
205
}
201
- sql := fmt .Sprintf (getJobSQL , not , excludedJobIDs )
206
+ sql := fmt .Sprintf (getJobSQL , s . currMinJobID , not , excludedJobIDs )
202
207
rows , err := se .Execute (context .Background (), sql , label )
203
208
if err != nil {
204
209
return nil , errors .Trace (err )
@@ -387,6 +392,7 @@ func (s *jobScheduler) startDispatch() error {
387
392
if err := s .checkAndUpdateClusterState (false ); err != nil {
388
393
continue
389
394
}
395
+ s .refreshMinJobID ()
390
396
failpoint .InjectCall ("beforeAllLoadDDLJobAndRun" )
391
397
s .loadDDLJobAndRun (se , s .generalDDLWorkerPool , jobTypeGeneral )
392
398
s .loadDDLJobAndRun (se , s .reorgWorkerPool , jobTypeReorg )
@@ -645,6 +651,21 @@ func (*jobScheduler) markJobProcessing(se *sess.Session, job *model.Job) error {
645
651
return errors .Trace (err )
646
652
}
647
653
654
+ func (s * jobScheduler ) refreshMinJobID () {
655
+ now := time .Now ()
656
+ if now .Sub (s .lastRefreshMinIDTime ) < dispatchLoopWaitingDuration {
657
+ return
658
+ }
659
+ s .lastRefreshMinIDTime = now
660
+ minID , err := s .sysTblMgr .GetMinJobID (s .schCtx , s .currMinJobID )
661
+ if err != nil {
662
+ logutil .DDLLogger ().Info ("get min job ID failed" , zap .Error (err ))
663
+ return
664
+ }
665
+ // use max, in case all job are finished to avoid the currMinJobID go back.
666
+ s .currMinJobID = max (s .currMinJobID , minID )
667
+ }
668
+
648
669
func (d * ddl ) getTableByTxn (r autoid.Requirement , schemaID , tableID int64 ) (* model.DBInfo , table.Table , error ) {
649
670
var tbl table.Table
650
671
var dbInfo * model.DBInfo
0 commit comments