performance_schema.events_statements_current是唯一能获取完整DDL语句和真实执行状态的方式,因SHOW PROCESSLIST存在截断、仅显外层线程、不反映子任务状态等问题;需先启用performance_schema,再结合metadata_locks和threads等表联合诊断。

直接查 performance_schema.events_statements_current 是唯一能拿到完整 DDL 语句和真实执行状态的方式,SHOW PROCESSLIST 在绝大多数 DDL 场景下不可靠。
为什么 SHOW PROCESSLIST 看不到真正的 DDL 执行中状态
MySQL 5.7+ 默认关闭 show_compatibility_56,且 INFORMATION_SCHEMA.PROCESSLIST 的 INFO 列只保留前 1024 字节 —— 而一个带分区、大字段或 JSON 定义的 ALTER TABLE 很容易超长;更关键的是,像 ALGORITHM=INPLACE 这类 DDL 会被拆成多个内部阶段,PROCESSLIST 只反映最外层线程,不体现子任务状态。
常见错误现象:
-
State: Waiting for table metadata lock,但Info是NULL—— 实际可能是个没显式写出的 DDL 卡住了 - 用
mysqladmin processlist查到的语句比客户端里执行的短一截,误以为执行完了,其实是被截断了 - 客户端连接设置了过小的
max_allowed_packet,导致长 DDL 在协议层就被截断,服务端记录的也是残缺 SQL
必须先确认 performance_schema 已启用
它不是默认全开的。执行:
SELECT @@performance_schema;
返回 1 才有效。如果返回 0,需在 MySQL 配置文件中设置:
performance_schema = ON
并重启 mysqld(注意:仅动态设置 SET GLOBAL performance_schema = ON 不生效)。
启用后,DDL 相关事件才可能被记录到以下三张表中:events_statements_current、metadata_locks、threads。
查正在执行的 DDL:过滤 EXECUTING + 关键词
STATE = 'EXECUTING' 是判断“真正在跑”的核心条件,不是 QUEUED 或 CALCULATING。DDL 语句关键词包括 ALTER、CREATE、DROP、RENAME、TRUNCATE。
执行:
SELECT THREAD_ID, SQL_TEXT, STATE, TIMER_WAIT FROM performance_schema.events_statements_current WHERE (SQL_TEXT LIKE 'ALTER %' OR SQL_TEXT LIKE 'CREATE %' OR SQL_TEXT LIKE 'DROP %' OR SQL_TEXT LIKE 'RENAME %' OR SQL_TEXT LIKE 'TRUNCATE %') AND STATE = 'EXECUTING';
注意点:
-
TIMER_WAIT单位是皮秒(10⁻¹² 秒),除以 10¹² 可得秒数,用来估算已运行时长 - 若结果为空,不代表没 DDL,很可能是卡在元数据锁等待中 —— 此时要立刻查
performance_schema.metadata_locks - 该查询只返回当前快照,DDL 执行极快时可能错过;建议配合轮询或监控脚本
DDL 卡住时必须连查的三张表
单看 events_statements_current 只能看到“语句”,看不到“为什么卡”。真正排障要三表联动:
-
performance_schema.metadata_locks:看谁持有SUPER或EXCLUSIVE锁,以及谁在等待 -
performance_schema.threads:通过THREAD_ID关联,确认线程是否活跃、用户、host、是否被 kill -
information_schema.INNODB_TRX:查是否有长事务未提交,阻塞了 DDL 的元数据锁获取
典型组合查法:
SELECT t.PROCESSLIST_USER, t.PROCESSLIST_HOST, t.PROCESSLIST_DB, m.OBJECT_SCHEMA, m.OBJECT_NAME, m.LOCK_TYPE, m.LOCK_DURATION, trx.trx_started, trx.trx_state FROM performance_schema.metadata_locks m JOIN performance_schema.threads t ON m.OWNER_THREAD_ID = t.THREAD_ID LEFT JOIN information_schema.INNODB_TRX trx ON t.PROCESSLIST_ID = trx.trx_mysql_thread_id WHERE m.LOCK_STATUS = 'PENDING';
这条语句能快速定位“谁在等锁、等什么锁、谁可能在持锁”。
DDL 的复杂性不在语法,而在它对元数据锁的强依赖和多阶段执行模型。不查 metadata_locks 就直接 kill 线程,很可能只是把问题从“卡住”变成“死锁回滚”,反而延长影响时间。


















