DM: optimistic shard DDL conflict on single source has no recovery path (unlock-ddl-lock rejects skip-and-wait-for-redirect; force-remove ignored)
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 464
- Forks
- 313
- Avg merge
- 4d 7h
- Merged PRs (30d)
- 14
Description
What did you do?
Run an optimistic shard-merge task on a single source (two databases of one MySQL instance merged into one downstream table). Execute a conflicting DDL on one branch, e.g. ALTER TABLE db1.tb1 CHARACTER SET utf8mb4 COLLATE utf8mb4_bin vs ALTER TABLE db2.tb1 CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci (different collations).
What did you expect to see?
The conflict can be resolved through the documented manual path (unlock-ddl-lock, correcting the upstream, or restarting the task).
What did you see instead?
The lock enters skip and wait for redirect and every recovery path fails:
unlock-ddl-lock(skip/exec) → 38020 "lock ... is in skip and wait for redirect status, not conflicted" (Optimist.UnlockLockonly acceptsConflictDetectedoperations)unlock-ddl-lock --force-remove→ same 38020 (the optimistic branch ignoresreq.ForceRemove;dm/master/server.go:959-965only passesreq.Op)- upstream correction DDL never arrives: the same binlog stream is blocked at the conflicting DDL (checkpoint frozen)
stop-task+start-task: the lock is recreated from etcd and replay conflicts again
The task is permanently stuck; the only way out is remove-meta/recreate, which loses the checkpoint.
Root cause
Optimist.UnlockLockrejects any operation whose conflict stage is notConflictDetected(dm/master/shardddl/optimist.go:270-278)Server.UnlockDDLLockoptimistic branch ignoresreq.ForceRemove(dm/master/server.go:959-965)- single source: both branches share one binlog stream, so no other source can drive the redirect (multi-source recovery was not verified in this environment)
Versions
- tiflow master 52c8e141f; also present on release-8.5
Note
The conflict detection itself is correct (schemacmp reports "incompatible collation"); the broken part is the recovery path for the ConflictSkipWaitRedirect state. Single-source optimistic shard merge has no code check or test coverage (all optimistic tests use double sources).
Production reachability
- Trigger prerequisites:
shard-mode: optimistic(explicit user config) + a conflicting DDL across branches (different collation, column-type change, ADD NOT NULL, etc. — the conflict set DM documents as unsupported) + single-source topology (two databases of one MySQL instance sharing one binlog stream). - Frequency: medium-low (requires the optimistic-mode + conflict-DDL combination). Single-source optimistic shard merge is a legal configuration (no code check rejects it; no test covers it — all optimistic tests use double sources).
- Consequence: task permanently stuck (checkpoint frozen at the conflicting DDL), sync interrupted; recovery requires
remove-meta/recreate, losing the checkpoint. The documented manual recovery path (unlock-ddl-lock) is unusable for theskip and wait for redirectstate. - Reachability: medium (config-combination gate). Multi-source optimistic recovery was not verified in this environment — it may be recoverable via another source driving the redirect; the single-source deadlock is reproduced deterministically.
Suggested labels
area/dm, type/bug, affects-8.5, severity/major, impact/func-failure, subject/replication-interruption (label add requires repo admin/triage rights, which the reporter does not have).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in dm/master/shardddl/optimist.go around Optimist.UnlockLock and dm/master/server.go around lines 959-965, then run the existing optimistic shard-DDL tests. Add coverage for a single-source conflict in ConflictSkipWaitRedirect and verify that unlock or force removal recovers the task without removing metadata or losing the checkpoint.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, mysql
- Domain
- backend, data-engineering, databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 62/100