直接执行show variables like 'slow_query_log';,返回on表示已启用,返回off则未开启;还需检查slow_query_log_file路径是否可写、long_query_time阈值是否合理(如设为1.0)。

如何确认 MySQL 是否已启用慢查询日志
默认情况下,MySQL 的慢查询日志是关闭的,即使你配置了相关参数,也必须显式启用才能生效。最直接的验证方式是查 slow_query_log 变量值:
SHOW VARIABLES LIKE 'slow_query_log';
返回 OFF 就说明没开;返回 ON 也不代表万事大吉——还要检查 slow_query_log_file 路径是否可写、long_query_time 是否设得合理(例如设为 0.1 才能捕获毫秒级慢操作)。
-
long_query_time是浮点数,单位秒,5.7+ 支持微秒精度(如0.05),但低于 1 秒需确认 MySQL 版本是否支持 - 若使用 Percona Server 或 MariaDB,还可能有
log_slow_rate_limit或log_slow_verbosity等扩展控制项,别漏掉 - 动态开启需执行
SET GLOBAL slow_query_log = ON,但该设置在重启后失效,必须写入配置文件才持久
如何安全地配置 slow_query_log_file 路径
日志路径不当是敏感数据泄漏的高发点:比如写到 Web 目录下,或用相对路径导致日志被写入不可控位置。MySQL 会以运行用户(通常是 mysql)身份写日志,所以路径权限必须严格限制。
- 绝对路径优先,例如
/var/log/mysql/mysql-slow.log,避免./slow.log这类相对路径 - 确保目录属主为
mysql,权限为750或更严,禁止 world-readable(chmod 750 /var/log/mysql) - 不要把日志放在
/tmp或用户家目录,这些位置容易被其他进程读取或清理 - 如果用容器部署,注意挂载卷的 UID/GID 是否与容器内
mysql用户一致,否则日志写入失败且无明显报错
为什么不能让慢查询日志记录完整 SQL(尤其含 WHERE 条件)
MySQL 默认会把整条 SQL(包括 WHERE user_id = '12345'、AND token = 'abc...')原样记入日志,这等于把脱敏前的敏感查询明文存盘。这不是功能缺陷,而是设计如此——它不区分字段语义,只做字符串记录。
- 开启
log_queries_not_using_indexes会加剧风险:大量低效查询带参数全量落盘 -
min_examined_row_limit可缓解,但无法解决核心问题;它只过滤扫描行数少的语句,对“快但带敏感条件”的查询无效 - 真正可行的防护是:禁用
log_slow_filter(5.7+ 不支持)、改用代理层(如 ProxySQL)或应用层脱敏,MySQL 自身不提供字段级日志脱敏能力 - 审计合规场景下,建议将慢日志仅用于性能分析,另起通道(如通过
performance_schema.events_statements_history_long)抓取去敏后的摘要
如何限制慢查询日志体积并防止覆盖关键时段数据
慢日志不会自动轮转,mysqldumpslow 或手动 mv 都不是原子操作,直接重命名可能丢失正在写入的日志内容。MySQL 本身不支持内置 rotate,必须靠外部机制兜底。
- 用
logrotate配合create 640 mysql mysql和postrotate mysqladmin flush-logs是最稳妥方案 - 务必在
my.cnf中设置slow_query_log_timestamp_always = ON(8.0.26+),否则日志时间戳可能缺失,影响归档排序 - 避免用
SET GLOBAL slow_query_log_file = ...动态切换路径,这会清空当前日志且不保证原子性 - 如果磁盘空间紧张,宁可调高
long_query_time或关闭日志,也不要允许日志无限增长——一次误配的long_query_time = 0可能在几小时内打爆磁盘
真正难处理的是「既要审计又要防泄漏」这个矛盾点:MySQL 慢日志天生不是为安全审计设计的,它不加密、不脱敏、不鉴权。如果你的合规要求明确指向「查询内容不可见」,那就得接受一个事实——不能依赖它作为唯一审计源。











