func (d *ddl) doDDLJob(ctx context.Context, job *model.Job) error { // for every DDL, we must commit current transaction. if err := ctx.CommitTxn(); err != nil { return errors.Trace(err) } var startTS uint64 err := kv.RunInNewTxn(d.store, true, func(txn kv.Transaction) error { t := meta.NewMeta(txn) var err error job.ID, err = t.GenGlobalID() startTS = txn.StartTS() return errors.Trace(err) }) if err != nil { return errors.Trace(err) } ddlQuery, _ := ctx.Value(context.QueryString).(string) job.Query = ddlQuery // Create a new job and queue it. err = kv.RunInNewTxn(d.store, true, func(txn kv.Transaction) error { t := meta.NewMeta(txn) err1 := t.EnQueueDDLJob(job) return errors.Trace(err1) }) if err != nil { return errors.Trace(err) } // notice worker that we push a new job and wait the job done. asyncNotify(d.ddlJobCh) log.Warnf("[ddl] start DDL job %v", job) var historyJob *model.Job jobID := job.ID // for a job from start to end, the state of it will be none -> delete only -> write only -> reorganization -> public // for every state changes, we will wait as lease 2 * lease time, so here the ticker check is 10 * lease. ticker := time.NewTicker(chooseLeaseTime(10*d.lease, 10*time.Second)) startTime := time.Now() jobsGauge.WithLabelValues(JobType(ddlJobFlag).String(), job.Type.String()).Inc() defer func() { ticker.Stop() jobsGauge.WithLabelValues(JobType(ddlJobFlag).String(), job.Type.String()).Dec() retLabel := handleJobSucc if err != nil { retLabel = handleJobFailed } handleJobHistogram.WithLabelValues(JobType(ddlJobFlag).String(), job.Type.String(), retLabel).Observe(time.Since(startTime).Seconds()) }() for { select { case <-d.ddlJobDoneCh: case <-ticker.C: } historyJob, err = d.getHistoryDDLJob(jobID) if err != nil { log.Errorf("[ddl] get history DDL job err %v, check again", err) continue } else if historyJob == nil { log.Warnf("[ddl] DDL job %d is not in history, maybe not run", jobID) continue } // if a job is a history table, the state must be JobDone or JobCancel. if historyJob.State == model.JobDone { return nil } return errors.Trace(historyJob.Error) } }