profile 是 mysql 旧版查询阶段耗时分析功能,因不稳定、不维护、不支持预编译语句及精确等待分类,自 5.7 弃用、8.0 移除;现推荐 performance schema 或慢日志 + pt-query-digest 替代。

PROFILE 是什么,为什么它现在基本没用了
MySQL 的 PROFILE 功能(通过 SET profiling = 1 开启)曾用于查看某条语句在各执行阶段的耗时,比如 parsing、executing、sending data。但它从 MySQL 5.7 开始被标记为 deprecated,8.0 完全移除。官方明确不维护,且结果不稳定——同一语句多次执行,SHOW PROFILES 可能漏掉阶段,或把并发线程的耗时混在一起。
- 不支持 prepared statement 的完整追踪
- 无法区分 CPU 时间和等待时间(比如锁等待、IO 等待全算进“executing”里)
- 查询计划变更后,profile 阶段名可能错位(比如 optimizer 初始化阶段被标成 “statistics”)
-
SHOW PROFILE FOR QUERY N中的 N 是会话内序号,不是 query_id,重连即重置,线上复现困难
替代方案:用 Performance Schema 查真实指令周期
真正能对应到“指令周期”级(如 mutex wait、file I/O、CPU cycles)的,只有 Performance Schema(PFS)。它默认开启(performance_schema = ON),但需手动启用对应消费者和仪器。
- 先确认关键配置已开:
performance_schema_events_stages_history_long_enabled = ON(记录长历史)、performance_schema_events_statements_history_long_enabled = ON - 执行前设置会话级过滤:
SET performance_schema_events_stages_history_long_size = 1000(避免被截断) - 用
SELECT * FROM performance_schema.events_statements_history_long WHERE SQL_TEXT LIKE '%your_query%'找到EVENT_ID,再关联events_stages_history_long查每个阶段耗时
常见陷阱:
- 默认只采集 top-N 阶段,
stages表可能为空,必须开_history_long类表 -
TIMER_WAIT是皮秒单位,要除以 1000000000000 转成秒,直接看数字容易误判 - 如果查询含子查询,每个子查询是独立 EVENT_ID,需递归关联,不能只盯最外层
更轻量、更准的现场诊断:使用 slow log + pt-query-digest
当你要快速定位“哪条语句卡在哪个环节”,比 PFS 更实用的是慢日志配合分析工具。关键是把 long_query_time 设低(比如 0.1),并打开 log_slow_extra = ON(MySQL 8.0.26+)。
-
log_slow_extra会输出Query_time、Lock_time、Rows_sent、Rows_examined,还新增Rows_affected和InnoDB_trx_id - 配合
pt-query-digest --filter '$event->{Bytes} > 1024' /var/lib/mysql/slow.log,能筛出高网络开销语句 - 注意:
Lock_time包含所有锁等待(不只是 InnoDB row lock),如果它远大于Query_time,说明有显式锁(SELECT ... FOR UPDATE)或 DDL 阻塞
容易忽略的一点:
-
log_output = FILE时,slow log 写入有缓冲,重启或 flush logs 前可能丢失最后几条;生产环境建议设log_output = TABLE,查mysql.slow_log更可靠
想看 CPU 指令级?别在 MySQL 里硬刚
MySQL 本身不暴露 CPU cycle、cache miss、branch misprediction 这类硬件指标。真需要这些,得靠外部工具:
- Linux 下用
perf record -e cycles,instructions,cache-misses -p $(pgrep mysqld)抓一段时间,再perf script分析热点函数 - 但注意:mysqld 是多线程,
-p只能抓主线程,要全面得加--call-graph dwarf并配合线程名过滤(如mysqld --thread-handling=pool-of-threads时线程名是thread/1) -
perf结果里看到大量row_search_mvcc或dict_table_stats_update,说明瓶颈在 MVCC 版本链遍历或统计信息更新,这时优化方向就不是 SQL 写法,而是调整innodb_stats_auto_recalc或加索引覆盖
最常被跳过的一步:
-
perf默认采样频率是 4000Hz,对短查询(-F 10000 提高频率,否则看到的全是“睡眠函数”
事情说清了就结束











