MySQL不提供DDL实时进度查询功能,仅能通过锁状态、等待链、INNODB_METRICS累计值或外部工具(如pt-online-schema-change)间接判断;其本质是黑盒操作。

MySQL 本身不提供直接查询“DDL 进度”的内置视图或函数——ALTER TABLE、CREATE INDEX 等 DDL 操作在执行时,不会像长事务那样暴露百分比或剩余时间。所谓“查进度”,实际只能查到它是否在运行、是否被阻塞、是否持有锁,以及(仅限特定场景)是否在 INFORMATION_SCHEMA.PROCESSLIST 或 performance_schema 中留下可观察痕迹。
为什么 SHOW PROCESSLIST 看不到 DDL 的实时进度?
MySQL 的 SHOW PROCESSLIST 或 information_schema.PROCESSLIST 只显示线程状态(如 altering table、copy to tmp table),但这些状态是粗粒度的,不反映完成比例。例如:
-
altering table可能刚启动,也可能已执行 90% —— 无法区分 -
copy to tmp table在 MySQL 5.7+ 中已被弃用,实际常见的是waiting for handler commit或rebuilding index(取决于存储引擎和版本) - InnoDB 的在线 DDL(
ALGORITHM=INPLACE)多数阶段不进入 processlist 的活跃状态,而是后台异步执行
如何判断 DDL 是否卡住或被阻塞?
重点不是“进度”,而是“是否异常停滞”。需结合锁与等待链分析:
- 查阻塞源:
SELECT * FROM performance_schema.data_locks WHERE OBJECT_SCHEMA = 'your_db' AND OBJECT_NAME = 'your_table';
- 查等待关系:
SELECT * FROM performance_schema.data_lock_waits;
- 查活跃事务及锁等待:
SELECT * FROM information_schema.INNODB_TRX\G
,重点关注TRX_STATE = 'LOCK WAIT'和TRX_WAITING_LOCK_ID - 确认 DDL 线程 ID 后,再查其在
performance_schema.threads中的PROCESSLIST_INFO字段,有时会包含 SQL 片段
MySQL 8.0+ 中唯一接近“进度”的线索:INNODB_METRICS
部分 DDL 操作(如 CREATE INDEX)会触发 InnoDB 内部计数器,可通过 INNODB_METRICS 间接观察:
- 启用指标:
SET GLOBAL innodb_monitor_enable = 'ddl_drop_table,ddl_create_index';
- 查询当前累计值:
SELECT NAME, COUNT FROM information_schema.INNODB_METRICS WHERE NAME LIKE 'ddl%';
- 注意:这不是实时进度条,而是自实例启动以来的累计操作次数;对单个 DDL 无意义,仅可用于趋势判断或确认引擎层是否响应
- 该功能默认关闭,且指标粒度粗、不可重置,生产环境慎用
真正可行的替代方案:从应用层控制 + 日志观测
如果你需要可靠进度反馈,必须放弃“MySQL 原生查进度”思路,转为外部可控:
- 对大表 DDL,优先使用
pt-online-schema-change或gh-ost:它们会在 stdout 输出进度百分比,并写入日志文件 - 用
strace -p $(pgrep mysqld) -e trace=open,read,write观察临时文件读写(仅限调试,性能开销大) - 监控磁盘 I/O 和
ibdata1/ibtmp1文件增长(如ls -lh /var/lib/mysql/ibtmp1),适用于COPY算法类 DDL - 设置
innodb_print_ddl_logs = ON(MySQL 8.0.23+),DDL 日志会输出到 error log,含阶段标记(如stage: 3/5),但需配合log_error_verbosity = 3
DDL 进度本质上是个黑盒,MySQL 不暴露中间状态。与其反复刷新 SHOW PROCESSLIST,不如提前评估操作耗时、预留足够超时窗口、并用工具链做可中断/可观测的变更。


















