MySQL 5.7+ 中 long_query_time 必须设为浮点数(如 1.0)才生效,整数赋值会静默失败;需同时开启 slow_query_log = ON,验证须用全新会话执行 SLEEP 并检查慢日志落地。

long_query_time 必须设为浮点数才生效
MySQL 5.7+ 版本对 long_query_time 的动态赋值做了严格校验:写 SET GLOBAL long_query_time = 1 不起作用,必须写成 SET GLOBAL long_query_time = 1.0。整数形式会被忽略,返回值看似变了(SELECT @@global.long_query_time 显示 1.000000),但实际日志不触发——这是最常被忽略的“静默失败”原因。
实操建议:
- 永远用小数形式赋值,哪怕值是整数,如
1.0、2.0、0.5 - 配置文件
my.cnf中也建议统一写小数(long_query_time = 1.0),避免版本差异引发歧义 - 执行后立刻验证:
SELECT @@global.long_query_time返回值应为精确浮点,如1.000000,不是1
只改阈值不开启 slow_query_log = ON,等于白配
long_query_time 是“计时器”,slow_query_log 才是“录音机”。两者缺一不可。常见错误是反复调低阈值却始终看不到日志,根本原因是 slow_query_log 仍为 OFF。
实操建议:
- 先确认开关状态:
SHOW VARIABLES LIKE 'slow_query_log',返回值必须是ON(不是1或TRUE) - 动态开启:
SET GLOBAL slow_query_log = 'ON'(注意引号,字符串值更稳妥) - 新连接才生效:已存在的客户端连接不会自动继承新全局值,需重连或手动执行
SET SESSION slow_query_log = 'ON' - 检查路径权限:
SHOW VARIABLES LIKE 'slow_query_log_file',确保 MySQL 进程对该路径有写权限(SELinux、AppArmor、父目录不存在都可能拦截)
线上不要设低于 0.5,尤其别碰 0
设 long_query_time = 0 看似“全量捕获”,实际会导致日志爆炸、IO 压力陡增、磁盘快速写满;而 0.1 在高并发 OLTP 场景下,会把大量毫秒级查询(如 SELECT id FROM users WHERE id = ?)全塞进日志,反而掩盖真实瓶颈。
实操建议:
- 线上起步值推荐
1.0秒,观察一周慢日志量和业务体感 RT(比如核心接口 P95 是 300ms,再考虑下调至0.3) - 微秒精度(如
0.15)仅在 MySQL 5.7+ 生效;旧版本会向下取整到秒,设0.15实际等同于0 - 若配合
log_queries_not_using_indexes = ON,务必加min_examined_row_limit = 1000(该参数只能在配置文件中设置并重启生效),否则日志全是噪音
验证是否真生效,别信 SHOW VARIABLES
SHOW VARIABLES LIKE 'long_query_time' 返回的是当前会话值,可能和全局不一致;SELECT @@long_query_time 同样受会话影响。最可靠验证方式是“端到端触发+落地检查”。
实操建议:
- 新开终端,用
mysql -u root -p连接(确保全新会话) - 执行
SELECT SLEEP(1.1)(假设你设了1.0) - 立刻
tail -f /var/log/mysql/mysql-slow.log查看是否出现该语句 - 再执行一条明确未走索引的查询(如
SELECT * FROM users WHERE name LIKE '%x%',且name无索引),确认是否也进日志 - 注意:如果
log_output = TABLE,要查SELECT * FROM mysql.slow_log,且确认该表引擎不是 CSV(CSV 引擎不支持 INSERT)
真正难的不是设一个数字,而是让这个数字在所有连接、所有版本、所有日志输出模式下都稳定触发——浮点写法、开关显式开启、路径权限、验证方式,四者缺一不可。


















