pingcap / pingcap/tiflow

DM: optimistic shard DDL conflict on single source has no recovery path (unlock-ddl-lock rejects skip-and-wait-for-redirect; force-remove ignored)

Open
#12,840 0 comments 0 reactions 0 assignees View on GitHub

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.UnlockLock only accepts ConflictDetected operations)
  • unlock-ddl-lock --force-remove → same 38020 (the optimistic branch ignores req.ForceRemove; dm/master/server.go:959-965 only passes req.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.UnlockLock rejects any operation whose conflict stage is not ConflictDetected (dm/master/shardddl/optimist.go:270-278)
  • Server.UnlockDDLLock optimistic branch ignores req.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 the skip and wait for redirect state.
  • 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.