@@ -64,6 +64,7 @@ import (
64
64
"github.com/pingcap/tidb/pkg/util/dbterror"
65
65
"github.com/pingcap/tidb/pkg/util/dbterror/exeerrors"
66
66
"github.com/pingcap/tidb/pkg/util/gcutil"
67
+ "github.com/pingcap/tidb/pkg/util/generic"
67
68
"github.com/pingcap/tidb/pkg/util/syncutil"
68
69
"github.com/tikv/client-go/v2/tikvrpc"
69
70
clientv3 "go.etcd.io/etcd/client/v3"
@@ -366,15 +367,17 @@ type ddlCtx struct {
366
367
ownerManager owner.Manager
367
368
schemaSyncer syncer.SchemaSyncer
368
369
stateSyncer syncer.StateSyncer
369
- ddlJobDoneCh chan struct {}
370
- ddlEventCh chan <- * statsutil.DDLEvent
371
- lease time.Duration // lease is schema lease, default 45s, see config.Lease.
372
- binlogCli * pumpcli.PumpsClient // binlogCli is used for Binlog.
373
- infoCache * infoschema.InfoCache
374
- statsHandle * handle.Handle
375
- tableLockCkr util.DeadTableLockChecker
376
- etcdCli * clientv3.Client
377
- autoidCli * autoid.ClientDiscover
370
+ // ddlJobDoneChMap is used to notify the session that the DDL job is finished.
371
+ // jobID -> chan struct{}
372
+ ddlJobDoneChMap generic.SyncMap [int64 , chan struct {}]
373
+ ddlEventCh chan <- * statsutil.DDLEvent
374
+ lease time.Duration // lease is schema lease, default 45s, see config.Lease.
375
+ binlogCli * pumpcli.PumpsClient // binlogCli is used for Binlog.
376
+ infoCache * infoschema.InfoCache
377
+ statsHandle * handle.Handle
378
+ tableLockCkr util.DeadTableLockChecker
379
+ etcdCli * clientv3.Client
380
+ autoidCli * autoid.ClientDiscover
378
381
379
382
* waitSchemaSyncedController
380
383
* schemaVersionManager
@@ -618,6 +621,27 @@ func (dc *ddlCtx) notifyReorgWorkerJobStateChange(job *model.Job) {
618
621
rc .notifyJobState (job .State )
619
622
}
620
623
624
+ func (dc * ddlCtx ) initJobDoneCh (jobID int64 ) {
625
+ dc .ddlJobDoneChMap .Store (jobID , make (chan struct {}, 1 ))
626
+ }
627
+
628
+ func (dc * ddlCtx ) getJobDoneCh (jobID int64 ) (chan struct {}, bool ) {
629
+ return dc .ddlJobDoneChMap .Load (jobID )
630
+ }
631
+
632
+ func (dc * ddlCtx ) delJobDoneCh (jobID int64 ) {
633
+ dc .ddlJobDoneChMap .Delete (jobID )
634
+ }
635
+
636
+ func (dc * ddlCtx ) notifyJobDone (jobID int64 ) {
637
+ if ch , ok := dc .ddlJobDoneChMap .Load (jobID ); ok {
638
+ select {
639
+ case ch <- struct {}{}:
640
+ default :
641
+ }
642
+ }
643
+ }
644
+
621
645
// EnableTiFlashPoll enables TiFlash poll loop aka PollTiFlashReplicaStatus.
622
646
func EnableTiFlashPoll (d any ) {
623
647
if dd , ok := d .(* ddl ); ok {
@@ -711,7 +735,7 @@ func newDDL(ctx context.Context, options ...Option) *ddl {
711
735
uuid : id ,
712
736
store : opt .Store ,
713
737
lease : opt .Lease ,
714
- ddlJobDoneCh : make ( chan struct {}, 1 ),
738
+ ddlJobDoneChMap : generic. NewSyncMap [ int64 , chan struct {}]( 10 ),
715
739
ownerManager : manager ,
716
740
schemaSyncer : schemaSyncer ,
717
741
stateSyncer : stateSyncer ,
@@ -1177,6 +1201,7 @@ func (d *ddl) DoDDLJob(ctx sessionctx.Context, job *model.Job) error {
1177
1201
1178
1202
// worker should restart to continue handling tasks in limitJobCh, and send back through task.err
1179
1203
err := <- task .errChs [0 ]
1204
+ defer d .delJobDoneCh (job .ID )
1180
1205
if err != nil {
1181
1206
// The transaction of enqueuing job is failed.
1182
1207
return errors .Trace (err )
@@ -1214,13 +1239,18 @@ func (d *ddl) DoDDLJob(ctx sessionctx.Context, job *model.Job) error {
1214
1239
recordLastDDLInfo (ctx , historyJob )
1215
1240
}()
1216
1241
i := 0
1242
+ notifyCh , ok := d .getJobDoneCh (job .ID )
1243
+ if ! ok {
1244
+ // shouldn't happen, just give it a dummy one
1245
+ notifyCh = make (chan struct {})
1246
+ }
1217
1247
for {
1218
1248
failpoint .Inject ("storeCloseInLoop" , func (_ failpoint.Value ) {
1219
1249
_ = d .Stop ()
1220
1250
})
1221
1251
1222
1252
select {
1223
- case <- d . ddlJobDoneCh :
1253
+ case <- notifyCh :
1224
1254
case <- ticker .C :
1225
1255
i ++
1226
1256
ticker = updateTickerInterval (ticker , 10 * d .lease , job , i )
0 commit comments