立刻生效需执行SET GLOBAL long_query_time = 1; 和 SET GLOBAL slow_query_log = 'ON';,新连接生效,旧连接需重连,并验证日志路径权限及SELinux/AppArmor限制。

怎么立刻生效地设置 long_query_time
MySQL 的慢查询阈值由 long_query_time 控制,单位是秒(支持小数),它决定“多慢才算慢”。默认值通常是 10.000000,对现代业务来说基本没用——等 10 秒才记日志,早炸了。
临时改(不重启、立即对新连接生效):
-
SET GLOBAL long_query_time = 1;—— 设为 1 秒,适合快速验证 -
SET GLOBAL slow_query_log = 'ON';—— 日志开关必须同时打开,否则阈值再低也白设 - 注意:已存在的连接不会自动更新该值,要重新连一次 MySQL 才能看到新阈值生效
- 执行
SHOW VARIABLES LIKE 'long_query_time';验证,别信自己记的数字
为什么配置文件里写 long_query_time = 0.5 却没用
很多人在 my.cnf 里加了 long_query_time = 0.5,重启后查还是 10。原因很实在:
- MySQL 8.0.14+ 和某些旧版本(如 5.7.21+)中,
long_query_time是动态变量,但**只有在启动时读取配置文件的值;运行中用SET GLOBAL修改后,配置文件的值就“作废”了**,重启会覆盖掉你之前的手动设置 - 更隐蔽的坑:
my.cnf可能被多个段落加载(比如[mysqld]和[server]),写错段落等于没写 - 路径权限问题:如果
slow_query_log_file指向的目录 MySQL 进程无写权限,整个慢日志会静默失败,slow_query_log看起来是ON,其实一条都不写
log_queries_not_using_indexes 不是可选项,是必开项
只靠 long_query_time 会漏掉大量“快但烂”的 SQL:比如一个没走索引的 SELECT * 在小表上 0.02 秒跑完,不进慢日志,但到了百万级数据就是灾难。
- 开启它:
SET GLOBAL log_queries_not_using_indexes = 'ON';或配置文件加log_queries_not_using_indexes = 1 - 搭配
min_examined_row_limit = 1000更实用:避免记录那些扫描几十行的无害查询,专注真正有风险的全表扫描 - 它和
long_query_time是“或”关系:满足任一条件(超时 or 未用索引)就会记日志
测试配置是否真起作用,别只看命令返回
执行完所有 SET GLOBAL,别急着去翻日志。先用最笨但最可靠的方式验证:
- 新开一个 MySQL 客户端连接(确保用的是新会话)
- 执行:
SELECT SLEEP(2);—— 如果long_query_time = 1,这条必须出现在慢日志里 - 执行:
SELECT * FROM users WHERE created_at > '2020-01-01';(确保created_at没索引),如果log_queries_not_using_indexes = ON,这条也得进去 - 用
tail -f /path/to/slow.log实时盯日志,别等第二天再查
最容易被忽略的一点:MySQL 服务账户(如 mysql 用户)对日志路径必须有写权限,且 SELinux 或 AppArmor 开启时可能拦截写入,这时候日志“看起来开了”,实际是空的。


















