MySQL原生不提供DDL进度百分比或剩余时间,但8.0.16+可通过performance_schema.events_stages_current中WORK_COMPLETED/WORK_ESTIMATED估算,仅限ALGORITHM=INPLACE的在线DDL;需先启用performance_schema及stage相关instruments和consumers,并结合data_lock_waits等判断是否卡锁或I/O瓶颈。

MySQL 原生不提供“还剩 X%”或“预计 Y 分钟”的直接接口,但 8.0.16+ 可通过 performance_schema.events_stages_current 中的 WORK_COMPLETED 和 WORK_ESTIMATED 字段做有限估算——前提是 DDL 使用了 ALGORITHM=INPLACE 且属于 InnoDB 支持的在线类型(如加索引、加列),否则字段为 NULL。
确认 performance_schema 相关监控已启用
没开就查不到任何 stage 进度,这是最常被跳过的前置步骤。
-
SELECT @@performance_schema必须返回1,否则需在配置文件中加performance_schema = ON并重启 - 检查 stage 仪器是否启用:
SELECT * FROM performance_schema.setup_instruments WHERE NAME LIKE 'stage/innodb/alter%',若ENABLED为NO,执行:UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'stage/innodb/alter%' - 检查 stage 消费者是否启用:
SELECT * FROM performance_schema.setup_consumers WHERE NAME LIKE '%stages%',若未启用,执行:UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE 'events_stages%'
查当前真正执行中的 DDL 语句和线程 ID
SHOW PROCESSLIST 的 State 列不可信:显示 altering table 只代表进入流程,可能卡在锁、I/O 或解析阶段;INFO 列还会被截断,看不到完整语句。
- 用
performance_schema.events_statements_current拿真实语句:SELECT THREAD_ID, SQL_TEXT, STATE FROM performance_schema.events_statements_current WHERE STATE = 'EXECUTING' AND SQL_TEXT REGEXP '^(ALTER|CREATE|DROP|RENAME|TRUNCATE)' - 只认
STATE = 'EXECUTING',QUEUED或CALCULATING都不算真正在干活 - 拿到
THREAD_ID后,才能关联到后续的 stage 进度查询
查 DDL 当前执行阶段与进度估算
不是所有 DDL 都有进度值。只有 ALGORITHM=INPLACE 且不触发全表拷贝的操作(如 ADD INDEX、ADD COLUMN)才可能填充 WORK_COMPLETED/WORK_ESTIMATED;ALGORITHM=COPY 或含外键重建时,这两字段基本为 NULL。
- 执行:
SELECT THREAD_ID, EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED FROM performance_schema.events_stages_current WHERE EVENT_NAME LIKE 'stage/innodb/%' AND WORK_ESTIMATED > 0 - 常见有效阶段包括:
stage/innodb/alter table (read PK and internal sort)、stage/innodb/alter table (write clustered index) - 进度百分比 ≈
ROUND(100 * WORK_COMPLETED / WORK_ESTIMATED, 2),但注意:这个“工作量”是 InnoDB 内部抽象单位,非时间或行数,不同阶段间不可比 - 剩余时间无法可靠推算,网上流传的
(TIMER_END - TIMER_START) * (WORK_ESTIMATED - WORK_COMPLETED) / WORK_COMPLETED公式误差极大,因TIMER_WAIT不稳定、阶段切换频繁、且未考虑 I/O 瓶颈
判断 DDL 是否卡住,而非慢
进度不动 ≠ DDL 慢,大概率是被阻塞。此时看 events_stages_current 可能为空或停留在 stage/sql/Waiting for table metadata lock,这说明问题不在 DDL 自身。
- 查锁等待:
SELECT * FROM performance_schema.data_lock_waits,若有记录,说明当前线程正等其他事务释放 MDL 或行锁 - 查长事务:
SELECT TRX_ID, TRX_STARTED, TRX_STATE FROM information_schema.INNODB_TRX ORDER BY TRX_STARTED LIMIT 5,重点关注运行超几分钟未提交的事务 - 查元数据锁持有者:
SELECT OBJECT_SCHEMA, OBJECT_NAME, LOCK_TYPE, LOCK_DURATION, LOCK_STATUS FROM performance_schema.metadata_locks WHERE LOCK_STATUS = 'GRANTED' -
SHOW ENGINE INNODB STATUS\G中的TRANSACTIONS和LATEST DETECTED DEADLOCK区域也能暴露阻塞源头,但需人工解读
真正难的不是算百分比,而是区分“还在干”和“根本没动”。WORK_COMPLETED 有值只是表象,背后可能是 I/O 饱和、内存不足、或某张小表被一个 SELECT ... FOR UPDATE 锁死了一整天——这些都不会体现在 stage 进度里,得靠锁视图和事务状态交叉验证。


















