Skip to content

Commit bc7ccc9

Browse files
committed
fix(mts): retry NOWAIT lock failures and resolve contextcheck lint errors
Under concurrent MTS workers, MySQL 8.0 may return ER_LOCK_NOWAIT (3572) when gap locks on the ghost table's secondary indexes conflict between parallel statements. This was not classified as retryable, causing the MTS worker to abort and cascade a migration failure. Changes: - Add errno 3572 (ER_LOCK_NOWAIT) to isRetryableApplyError alongside existing 1205 (lock wait timeout) and 1213 (deadlock) - Remove context.Background() fallback in ApplyDMLEventQueries; all callers already pass a valid context (resolves contextcheck lint) - Use the passed ctx parameter in applyMTSWorkerJob defer instead of mgtr.migrationContext.GetContext() (resolves contextcheck lint)
1 parent 8c0f999 commit bc7ccc9

2 files changed

Lines changed: 12 additions & 10 deletions

File tree

go/logic/applier.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -481,17 +481,22 @@ func isDeadlockError(err error) bool {
481481
}
482482

483483
// isRetryableApplyError reports whether a failed DML apply is a transient
484-
// concurrency error that should be retried. Under concurrent MTS workers both
485-
// InnoDB deadlocks (1213) and lock-wait timeouts (1205) are expected: gap locks
486-
// on the ghost table's secondary indexes cause contention between parallel
487-
// REPLACE INTO / DELETE FROM statements. Both are resolved by retrying the whole
488-
// transaction, mirroring MySQL's slave_transaction_retries behaviour.
484+
// concurrency error that should be retried. Under concurrent MTS workers the
485+
// following errors are expected: InnoDB deadlocks (1213), lock-wait timeouts
486+
// (1205), and NOWAIT lock failures (3572). Gap locks on the ghost table's
487+
// secondary indexes cause contention between parallel statements. All are
488+
// resolved by retrying the whole transaction, mirroring MySQL's
489+
// slave_transaction_retries behaviour.
489490
func isRetryableApplyError(err error) bool {
490491
var mysqlErr *drivermysql.MySQLError
491492
if !errors.As(err, &mysqlErr) {
492493
return false
493494
}
494-
return mysqlErr.Number == 1213 || mysqlErr.Number == 1205
495+
switch mysqlErr.Number {
496+
case 1205, 1213, 3572:
497+
return true
498+
}
499+
return false
495500
}
496501

497502
// retryOnLockWaitTimeout retries the given operation on MySQL lock wait timeout
@@ -1816,9 +1821,6 @@ func (apl *Applier) executeBatchWithWarningChecking(ctx context.Context, tx *gos
18161821
// ApplyDMLEventQueries applies multiple DML queries onto the _ghost_ table
18171822
func (apl *Applier) ApplyDMLEventQueries(ctx context.Context, dmlEvents [](*binlog.BinlogDMLEvent)) error {
18181823
var totalDelta int64
1819-
if ctx == nil {
1820-
ctx = context.Background()
1821-
}
18221824

18231825
err := func() error {
18241826
conn, err := apl.db.Conn(ctx)

go/logic/migrator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2130,7 +2130,7 @@ func (mgtr *Migrator) applyMTSWorkerJob(ctx context.Context, workerID int, appli
21302130
if applyErr != nil {
21312131
mgtr.commitBarrier.commit(job.sequenceNum)
21322132
mgtr.commitBarrier.completeDelegatedJob()
2133-
_ = base.SendWithContext(mgtr.migrationContext.GetContext(), mgtr.migrationContext.PanicAbort, applyErr)
2133+
_ = base.SendWithContext(ctx, mgtr.migrationContext.PanicAbort, applyErr)
21342134
}
21352135
}()
21362136

0 commit comments

Comments
 (0)