必须配对 slow_query_log 和 long_query_time 才能写入慢查询日志;临时开启用 SET GLOBAL 命令,永久配置需修改 my.cnf 并重启;验证需检查日志文件内容与 Slow_queries 状态值。

直接开就行,但必须配对 slow_query_log 和 long_query_time,否则日志根本不会写入。
临时开启:登录 MySQL 后立刻生效,但重启就丢
适合紧急排查,不用改配置、不重启服务:
-
SET GLOBAL slow_query_log = ON—— 必须设为ON(不是1或'ON'字符串,部分版本严格区分) -
SET GLOBAL long_query_time = 0.5—— 建议从0.5秒起步,10是默认值,对现代业务完全没用 -
SET GLOBAL log_queries_not_using_indexes = ON—— 这个开关能抓到“快但危险”的 SQL,比如全表扫描只查 10 行但数据量涨十倍就崩 - 执行完后,新连接才能看到生效的变量;当前会话需重新登录或执行
SELECT @@long_query_time确认
永久配置:写进 my.cnf,重启 MySQL 才生效
生产环境必须走这步,否则服务重启后日志自动关闭:
- 编辑
/etc/my.cnf或/etc/mysql/my.cnf,在[mysqld]段下添加: -
slow_query_log = 1—— 数值1/0更兼容,比ON/OFF更稳妥 -
slow_query_log_file = /var/log/mysql/slow.log—— 路径必须 MySQL 用户(通常是mysql)有写权限,先mkdir -p /var/log/mysql并chown mysql:mysql /var/log/mysql -
long_query_time = 0.1—— 可设到0.1(100ms),尤其在高并发 OLTP 场景,1秒已算严重延迟 -
log_queries_not_using_indexes = 1—— 强烈建议打开,很多慢查询不是因为时间长,而是因为没索引,等数据量上来才暴露
确认是否真在记录:别信配置,要看实际输出
光看 SHOW VARIABLES LIKE 'slow_query_log' 返回 ON 不代表日志在写,常见假成功:
- 检查日志文件是否存在且有内容:
tail -n 5 /var/log/mysql/slow.log,空文件说明没写入 - 运行一条明显慢的语句测试:
SELECT SLEEP(2),再立刻tail日志,没出现就是路径/权限/阈值三者之一错了 -
SHOW GLOBAL STATUS LIKE 'Slow_queries'查计数,如果一直为0,说明日志根本没触发 - 注意:
long_query_time在 5.7+ 支持微秒精度,但会话级设置(SET long_query_time)只影响当前连接,全局设置才管所有新连接
分析日志前先看关键字段:别被 Query_time 迷惑
日志里最该盯的是 Rows_examined 和 Rows_sent 的比值,而不是 Query_time:
-
Query_time: 0.084123看着快?但如果Rows_examined: 1240000且Rows_sent: 1,说明它扫了 124 万行才捞出 1 条,索引肯定有问题 -
Lock_time高意味着锁等待严重,可能是事务没及时提交或隔离级别太高 -
SET timestamp=...后面那条 SQL 才是真实执行语句,注意它可能被截断,完整 SQL 要结合应用日志或general_log对照 - 别手动翻日志,用
mysqldumpslow -t 10 -s t /var/log/mysql/slow.log快速排前 10 条最耗时的
真正难的不是开日志,而是判断哪条 SQL 值得优化——log_queries_not_using_indexes = 1 开着时,日志里大量“快但无索引”的查询最容易被忽略,它们才是未来最大的雷。


















