MySQL 8.0+ 中 SHOW PROFILE 基本没用,因其依赖的 information_schema.PROFILING 表已被移除,执行直接报错;唯一可靠替代是 Performance Schema,需启用相关消费者与仪器才能获取真实 CPU 时间。

show profile 为什么在 MySQL 8.0+ 里基本没用
MySQL 5.7 及更早版本中 SHOW PROFILE 确实能显示语句各阶段的 CPU 和 duration 耗时,但这个功能从 MySQL 8.0 开始被**默认禁用且不再维护**。执行 SHOW PROFILE 会直接报错 ERROR 1286 (42000): Unknown table 'PROFILING' in information_schema,因为 information_schema.PROFILING 表已被移除。即使你通过旧配置强行启用(如启动时加 --profiling=1),也仅限于调试环境,生产库不支持,且结果不可靠。
替代方案:用 Performance Schema 抓真实 CPU 时间
MySQL 8.0+ 的唯一可靠路径是开启 performance_schema 并启用相关消费者与仪器。它能捕获每个 SQL 语句在各个阶段(如 sql/SELECT, sql/filesort, sql/group_by)的真实 CPU 时间(单位为皮秒),而非粗略的 wall-clock duration。
实操步骤如下:
- 确认已启用:
SELECT VARIABLE_VALUE FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'performance_schema'返回ON - 启用关键消费者:
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME IN ('events_statements_history_long', 'events_waits_history_long') - 启用 CPU 时间采集:
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES', TIMED = 'YES' WHERE NAME LIKE 'statement/%' OR NAME LIKE 'stage/%' - 执行目标 SQL 后,查:
SELECT EVENT_NAME, TIMER_WAIT, CPU_TIME FROM performance_schema.events_statements_history_long WHERE SQL_TEXT LIKE '%your_query%' ORDER BY TIMER_START DESC LIMIT 1
注意:CPU_TIME 字段只在 MySQL 8.0.29+ 版本中可用;低于此版本只能依赖 TIMER_WAIT(总耗时),无法分离 CPU 与等待时间。
遇到 CPU 高但 CPU_TIME 却很低?说明瓶颈不在 MySQL 内部
如果某条 SQL 的 CPU_TIME 占 TIMER_WAIT 不足 20%,而系统级 top 显示 mysqld 进程 CPU 使用率却持续 >90%,那问题大概率出在:
- 操作系统层面:内核调度争抢、CPU 频率被限制(
cpupower frequency-info)、透明大页(transparent_hugepage)导致周期性卡顿 - 硬件层:NUMA 绑定不当、CPU 核心过热降频
- MySQL 外部:备份脚本、监控 agent、或同机其他进程(如 Java 应用)大量 fork 子进程触发系统调用风暴
此时再盯着 SQL 执行计划优化毫无意义——得切到 perf record -g -p $(pgrep mysqld) 或 ebpf tools 做栈采样,看 CPU 时间实际花在哪条系统调用上。
别把 SHOW PROCESSLIST 的 Sending data 当成 CPU 瓶颈信号
SHOW PROCESSLIST 中状态为 Sending data,常被误认为“正在大量计算”,其实它代表的是 **MySQL 正在向客户端网络缓冲区写入结果集**,本质是 IO 状态,不是 CPU 状态。真正反映 CPU 密集型操作的状态是 Creating sort index(filesort 在内存中排序)、Copying to tmp table on disk(磁盘临时表归并)、或 statistics(优化器估算成本阶段)。
验证方法:对处于 Sending data 的线程执行 KILL QUERY,如果客户端立刻断开但 mysqld 进程 CPU 不降,说明瓶颈不在该 SQL;如果 CPU 骤降,则可能是结果集过大导致网络协议栈反复拷贝(此时应限制 LIMIT 或改用游标分批拉取)。
真正要定位 CPU 瓶颈,得放弃“一条命令搞定”的幻想——SHOW PROFILE 是历史遗迹,Performance Schema 是当前事实标准,而最终是否真由 SQL 引发,必须交叉比对系统级指标。忽略这点,所有 EXPLAIN 和索引优化都可能白忙一场。


















