docs/agents/ddl/README.md
TiDB DDL is job-based and owner-driven: a SQL DDL statement is converted into a persistent DDL job, then the DDL owner schedules and runs the job on workers, gradually changing schema states and waiting for schema version synchronization across TiDB nodes.
The most common mistake is to implement “DDL behavior” directly in pkg/executor/ (SQL executor layer). That usually bypasses:
delete only → write only → reorg → public).This doc set is meant to be the first thing to read before touching DDL-related code.
docs/agents/ddl/* diverge during design/development, you MUST update the docs to match reality and call it out in the PR/issue.Before touching pkg/ddl/, answer these explicitly (write them down in the PR/issue if possible):
public throughout?mysql.tidb_ddl_job, mysql.tidb_ddl_reorg, ...)? Which fields must be backward compatible?docs/agents/ddl/01-execution-flow.mddocs/agents/ddl/02-job-lifecycle.mddocs/agents/ddl/03-reorg-backfill.mddocs/agents/ddl/04-dev-checklist.mddocs/agents/ddl/05-file-map.mddocs/agents/ddl/06-add-index.mddocs/agents/ddl/07-modify-column.mddocs/agents/ddl/08-partition-ddl.mdmodel.ActionModifyColumn → docs/agents/ddl/07-modify-column.mdmodel.ActionAddIndex, model.ActionAddPrimaryKey → docs/agents/ddl/06-add-index.mdmodel.ActionAddTablePartition, model.ActionDropTablePartition, model.ActionTruncateTablePartition → docs/agents/ddl/08-partition-ddl.mdmodel.ActionReorganizePartition, model.ActionExchangeTablePartition → docs/agents/ddl/08-partition-ddl.mdpkg/executor/ddl.go (DDLExec) receives a DDL AST node and calls into the DDL module.pkg/ddl/executor.go converts the statement to a model.Job (or multiple jobs), then submits it via JobSubmitter.JobSubmitter allocates IDs, writes the job into mysql.tidb_ddl_job, and notifies the owner-side scheduler.jobScheduler, which dispatches jobs into worker pools.sequenceDiagram
participant S as Session
participant X as DDLExec (pkg/executor/ddl.go)
participant E as DDL executor (pkg/ddl/executor.go)
participant J as JobSubmitter (pkg/ddl/job_submitter.go)
participant T as mysql.tidb_ddl_job
participant O as DDL Owner (jobScheduler)
participant W as ddl workers
participant V as Syncer (pkg/ddl/schemaver/syncer.go)
S->>X: Execute DDL statement (AST)
X->>E: ddl.Executor.*(stmt)
E->>J: deliver job(s) via limit channel
J->>T: allocate IDs + insert job record
J-->>O: notifyNewJobSubmitted()
O->>W: schedule & run job steps
W->>V: OwnerUpdateGlobalVersion + WaitVersionSynced
W->>T: move to history + delete from queue
W-->>E: close jobDone channel / notify
E-->>S: return result
pkg/executor/ddl.go: type DDLExec, (*DDLExec).Next dispatches AST → DDL module; handles transaction boundary and converts schema-outdated errors.pkg/ddl/ddl.go: NewDDL wires everything; (*ddl).Start starts submit loop and campaigns owner.pkg/ddl/executor.go: type Executor (called by SQL layer); converts statements → jobs; DoDDLJobWrapper waits for job completion.pkg/ddl/job_submitter.go: type JobSubmitter batches submission, allocates IDs, inserts into job table, and notifies scheduler.pkg/ddl/job_scheduler.go: owner-only scheduler; ownerListener.OnBecomeOwner starts jobScheduler and worker pools.pkg/ddl/job_worker.go: worker logic; transitOneJobStep / runOneJobStep drive state transitions and meta updates.pkg/ddl/schema_version.go + pkg/ddl/job_worker.go:updateGlobalVersionAndWaitSynced: global schema version update + WaitVersionSynced.pkg/ddl/schemaver/syncer.go: type Syncer implements schema version synchronization (etcd-based).pkg/ddl/systable/manager.go: storage access for job/MDL related system tables.pkg/domain/domain.go: creates DDL via ddl.NewDDL(...); initializes infosync + schema syncer, and orchestrates startup order.docs/agents/ddl/01-execution-flow.md — end-to-end call chain and responsibilities.docs/agents/ddl/02-job-lifecycle.md — job/version/state machines, schema sync, owner/failover.docs/agents/ddl/03-reorg-backfill.md — reorg/backfill and distributed backfill overview.docs/agents/ddl/04-dev-checklist.md — where-to-change, testing, and common pitfalls.docs/agents/ddl/05-file-map.md — quick “where is this implemented?” map inside pkg/ddl/.docs/agents/ddl/06-add-index.md — add-index deep dive (fast reorg, ingest, backfill-merge).docs/agents/ddl/07-modify-column.md — modify-column deep dive (reorg types, state machine).docs/agents/ddl/08-partition-ddl.md — partition DDL deep dive (state machine, reorg, GC).docs/design/2022-09-19-distributed-ddl-reorg.mddocs/design/2022-06-07-adding-index-acceleration.mddocs/design/2022-04-15-multi-schema-change.mddocs/design/2023-04-15-ddl-pause-resume.mddocs/design/2023-04-11-pause-user-ddl-when-upgrading.mddocs/design/2023-04-11-dist-task.md