Skip to content

DM: SplitDDL detaches ALGORITHM= / LOCK= qualifiers from the ALTER they qualify #12833

Description

@choudharypankaj

What did you do?

Replicate an ALTER TABLE carrying an ALGORITHM qualifier from MySQL/Aurora to TiDB.
Upstream:
ALTER TABLE db.orders ADD COLUMN c INT NULL, ALGORITHM=INSTANT;

What did you expect to see?

DM applies one statement downstream, preserving the qualifier:

ALTER TABLE db.orders ADD COLUMN c INT NULL, ALGORITHM = INSTANT

What did you see instead?

DM emits two statements — the operation loses its qualifier, and the qualifier becomes a standalone no-op:

dm-worker.log:
ddl.go:459 originSQL: ALTER TABLE db.orders ADD COLUMN c INT NULL, ALGORITHM=INSTANT
baseconn.go:184 query="ALTER TABLE db.orders ADD COLUMN c INT NULL" ← qualifier lost
baseconn.go:184 query="ALTER TABLE db.orders ALGORITHM = INSTANT" ← orphan

Root cause

dm/pkg/parser/common.go, SplitDDL(), *ast.AlterTableStmt case (line 295 on v8.5.5):

v.Specs = []*ast.AlterTableSpec{spec} // one emitted statement per AST spec

ALGORITHM/LOCK are modelled as their own AlterTableSpec (ast.AlterTableAlgorithm / ast.AlterTableLock), not as attributes of the operation, so per-spec splitting separates them.

The splitting is justified at dm/syncer/ddl.go:311:

// TiDB can't handle multi schema change DDL, so we split it here.

On TiDB v8.5.5 the premise no longer holds — both of these execute successfully:

ALTER TABLE t ADD COLUMN b INT NULL, ADD COLUMN c INT NULL, DROP COLUMN a;
ALTER TABLE t ADD COLUMN d INT NULL, ADD COLUMN e INT NULL, ALGORITHM=INSTANT;

Why it matters

Against a TiDB-only target the impact is cosmetic — TiDB ignores the qualifier semantically (isIgnorableSpec). But TiDB still records the original query text in the DDL job (setDDLJobQuery uses s.OriginText()), so the qualifier is meaningful to anything replicating onward from TiDB.

In an Aurora → DM → TiDB → TiCDC → Aurora topology, TiCDC forwards job.Query verbatim. Because DM strips the qualifier, the downstream MySQL receives a bare ALTER — and MySQL silently falls back to a full table rebuild when an instant operation isn't possible.

Versions of the cluster

DM version (run dmctl -V or dm-worker -V or dm-master -V):

DM version:       v8.5.5

Upstream MySQL/MariaDB server version:

Aurora MySQL 3.10.3 (MySQL 8.0.42)

Downstream TiDB cluster version (execute SELECT tidb_version(); in a MySQL client):

TiDB version:     v8.5.5
Downstream of TiDB (via TiCDC): Aurora MySQL 3.10.3

How did you deploy DM: tiup or manually?

Manually

Other interesting information (system version, hardware config, etc):

>
>

current status of DM cluster (execute query-status <task-name> in dmctl)

running

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area/dmIssues or PRs related to DM.contributionThis PR is from a community contributor.type/bugThe issue is confirmed as a bug.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions