docs/agents/ddl/01-execution-flow.md
This doc explains the execution skeleton of TiDB DDL and the responsibility boundary of each layer.
pkg/executor/ddl.goEntry: pkg/executor/ddl.go (type DDLExec, (*DDLExec).Next)
This is the SQL-layer wrapper for end-user DDL execution on the connected TiDB node: it maps DDL AST nodes to the DDL module and handles statement/transaction boundaries.
Responsibilities:
pkg/ddl/executor.go).Non-responsibilities (avoid putting logic here):
Entry: pkg/ddl/executor.go (type Executor, (*executor).DoDDLJobWrapper)
Think of this as the DDL framework client on the connected TiDB node: it validates/serializes statements into durable jobs, submits them, and blocks the session until completion.
The DDL module has its own “executor” (different from pkg/executor/). Its job is:
TableInfo, expand options).model.Job (or multiple jobs) and wrap it in ddl.JobWrapper.JobSubmitter by sending it into a bounded channel (deliverJobTask → limitJobCh).The waiting loop is in (*executor).DoDDLJobWrapper and includes:
StmtCtx.DDLJobID for KILL to cancel the job.mysql.tidb_ddl_jobEntry: pkg/ddl/job_submitter.go (type JobSubmitter, submitLoop, addBatchDDLJobs)
Key ideas:
limitJobCh and submitted in batch.mysql.tidb_ddl_job), then the submitter notifies the owner scheduler (notifyNewJobSubmitted).tidb_enable_fast_create_table is enabled, multiple create-table jobs may be merged into a single “batch create table” job.Entry: pkg/ddl/job_scheduler.go:OnBecomeOwner
owner.Manager, etcd-backed) to elect exactly one owner.jobScheduler and worker pools.This is why DDL execution must be resumable and driven by persistent job state.
Entrypoints:
pkg/ddl/job_scheduler.go (jobScheduler.start, scheduleLoop)pkg/ddl/job_worker.go (transitOneJobStep, runOneJobStep)The owner scheduler:
Workers run each job in small, persistent steps:
OwnerUpdateGlobalVersion + WaitVersionSynced).Entrypoints:
pkg/ddl/job_worker.go:updateGlobalVersionAndWaitSyncedpkg/ddl/schema_version.go:waitVersionSyncedpkg/ddl/schemaver/syncer.go (Syncer.WaitVersionSynced)After each schema state change, the owner:
This mechanism is fundamental to online DDL correctness: it ensures that once the job advances to the next schema state, all nodes have a consistent view (or are at least caught up enough to respect compatibility).
On completion:
Rule of thumb:
pkg/ddl/executor.gopkg/ddl/job_worker.go + specific DDL action files (table.go, schema.go, index.go, …)pkg/executor/ddl.go (keep thin)If the change modifies schema state transitions, job steps, or meta writes, it almost certainly belongs in pkg/ddl/.