必须手动验证慢查询日志启用状态:执行SHOW VARIABLES LIKE 'slow_query_log'确认值为ON,检查slow_query_log_file路径可写性及long_query_time设置一致性(注意5.7与8.0对小数精度处理差异)。

如何确认慢查询日志在升级前后都已正确启用
MySQL 5.7 和 8.0 对慢查询日志的默认行为有明显差异:5.7 默认关闭 slow_query_log,而 8.0 虽仍默认关闭,但部分云厂商镜像可能预启。必须手动验证,不能依赖“之前开过”这种假设。
- 执行
SHOW VARIABLES LIKE 'slow_query_log';,确认值为ON - 检查
slow_query_log_file路径是否可写(常见坑:/var/lib/mysql/hostname-slow.log权限不足,尤其升级后 datadir 所属用户可能从mysql变为mysqld) - 确认
long_query_time设置一致(例如都设为1.0),注意 8.0 支持微秒级(如0.5),5.7 只支持秒级小数,设0.5在 5.7 会被截断为0,导致日志爆炸 - 若用 Percona Server 或 MariaDB,还需核对
log_slow_admin_statements和log_slow_slave_statements是否同步开启
如何提取可比的慢查询样本集(避免时间窗口偏差)
直接对比“升级前一周”和“升级后一周”的日志行数毫无意义——流量峰谷、业务发布、缓存预热状态全不同。关键不是总量,而是相同业务场景下的代表性慢查询。
- 优先选取固定周期内由同一应用模块触发的慢查询,例如每天 02:00 的订单归档任务(可通过
SELECT ... FROM mysql.slow_log中的user_host和注释中的 trace ID 过滤) - 禁用
log_queries_not_using_indexes,否则升级后因索引优化导致“未走索引”查询减少,会干扰慢查统计基数 - 用
mysqldumpslow -s t -t 20 /path/to/slow.log分别提取升级前后 top 20 最耗时查询,人工比对 SQL 模板是否一致(注意参数化后的WHERE id = ?形式是否被统一归类) - 对同一 SQL 模板,用
pt-query-digest分别解析两个日志,输出 CSV 后用diff -u对比Query_time的中位数和 P95 延迟
为什么不能只看 slow.log 里的 Query_time
Query_time 仅反映语句从进入执行队列到返回结果的时间,不包含网络传输、客户端解析、连接等待等环节。升级后若并发连接数配置变更(如 max_connections 从 500 调到 2000),Query_time 可能下降,但实际端到端延迟未必改善。
- 必须结合 Performance Schema 查证:升级后执行
SELECT * FROM performance_schema.events_statements_summary_by_digest ORDER BY AVG_TIMER_WAIT DESC LIMIT 10;,比对相同DIGEST_TEXT的AVG_TIMER_WAIT和EXECUTIONS - 注意 8.0 默认启用
performance_schema,而 5.7 可能被关闭;若 5.7 未开,需回溯启用并重启采集,否则无法横向对比 - 某些慢查询在 8.0 中被优化器重写(如子查询转 semi-join),
DIGEST值会变,此时要按原始 SQL 文本做字符串模糊匹配,而非依赖 digest
如何识别 MySQL 升级引入的隐性性能退化
有些退化不会让某条 SQL 进 slow.log,但会让整体吞吐掉 10%——比如 8.0 默认开启 innodb_deadlock_detect,高并发更新场景下自旋开销增大;或 5.7 的 optimizer_switch='index_merge=on' 在 8.0 中默认关闭,导致某些复合条件走不到最优索引。
- 用
pt-stalk在升级前后相同负载下抓取 5 分钟的SHOW ENGINE INNODB STATUS、锁等待、线程状态快照,重点比对SEMAPHORES小节的 wait array slot 数量 - 检查
information_schema.INNODB_METRICS中lock_row_lock_time_avg和buffer_pool_hit_ratio的变化趋势(注意 8.0 中部分指标名有变更,如buffer_pool_hit_ratio→buffer_pool_hit_rate) - 对关键慢查询,强制用
EXPLAIN FORMAT=TREE(8.0)和EXPLAIN FORMAT=JSON(5.7)分别查看执行计划,关注rows_examined是否激增、是否出现Using temporary; Using filesort等降级标记
真正难的是把 slow.log 里一条 # Time: 2024-06-01T08:23:41.123456 和某次线上接口超时精确关联起来——这需要应用层打点记录 SQL digest + trace_id,并与数据库日志时间戳对齐。没做这层埋点,基准对比就始终隔着一层雾。



















