如何确认 MySQL 是否启用了错误日志和慢查询日志
MySQL 默认不一定开启这两类日志,尤其慢查询日志默认是关闭的。直接查
SHOW VARIABLES LIKE '%log%'可能返回一堆配置,但关键就看这几个:
log_error:显示错误日志路径(如
/var/log/mysql/error.log),若为空或为
NULL,说明错误日志未启用(常见于 MySQL 8.0+ 的 systemd 管理模式,日志可能走系统 journal)
slow_query_log:值为
OFF表示慢查询日志关闭;
ON才启用
slow_query_log_file:慢日志文件路径,若未显式设置,MySQL 会按数据目录 + 主机名生成默认路径(如
/var/lib/mysql/hostname-slow.log)
long_query_time:判定“慢”的阈值(单位秒),默认是
10.000000,生产环境建议调低到
1.0或
0.5
注意:
log_output决定日志输出方式,
FILE写文件,
TABLE写入
mysql.slow_log表(需同时启用
slow_query_log),
TABLE方式方便 SQL 查询分析,但有性能开销且不记录非查询语句(如
SET、
DELIMITER)。
错误日志里哪些内容必须立刻关注
错误日志不是用来“定期翻阅”的,而是出问题时第一排查入口。以下几类信息出现即需人工介入:
Aborted connection:频繁出现说明客户端异常断连,可能是网络抖动、超时设置不合理(如
wait_timeout太小),或应用未正确 close 连接
Out of memory或
Cannot allocate memory:不是 MySQL 内存配额超了,很可能是系统级 OOM killer 杀掉了 mysqld 进程,要查
dmesg -T | grep -i "killed process"
InnoDB: Database page corruption或
Failed to read from the .ibd file:物理页损坏,立即停止写入,用
innodb_force_recovery尝试导出数据
Plugin 'validate_password' is disabled类提示:不是错误,但说明插件加载失败,若依赖该插件做密码策略,实际策略并未生效
不要被大量
Starting crash recovery或
Shutdown completed刷屏干扰——只要不是高频重启,这些属于正常启停日志。
慢查询日志分析的实用命令与过滤技巧
直接
cat或
tail -f看原始日志效率极低。优先用官方工具
mysqldumpslow或结构化处理: 统计最慢的 10 条语句:
mysqldumpslow -s t -t 10 /var/lib/mysql/hostname-slow.log统计访问次数最多的 10 条:
mysqldumpslow -s c -t 10 /var/lib/mysql/hostname-slow.log只看锁定时间超过 2 秒的:
mysqldumpslow -s l -t 10 -g "Lock_time: [2-9]" /var/lib/mysql/hostname-slow.log如果日志是
TABLE方式存储,可直接 SQL 分析:
SELECT query_time, lock_time, rows_sent, rows_examined, sql_text FROM mysql.slow_log ORDER BY query_time DESC LIMIT 10;
注意:
mysqldumpslow会自动归并带不同参数的相同语句(如
WHERE id = 1和
WHERE id = 2都算作
WHERE id = N),但无法识别函数或子查询变化,真实场景中仍需结合
pt-query-digest做深度分析。
为什么开了慢日志却没记录明显慢的查询
常见原因不是配置漏了,而是语义或执行路径不符合记录条件:
查询在从库执行,但log_slow_slave_statements为
OFF(MySQL 5.7+ 默认关) 语句被优化器重写后实际执行很快(如命中覆盖索引,
rows_examined很小),但
query_time仍超阈值——此时
long_query_time是按实际执行耗时判断的,不受扫描行数影响 使用了
SQL_NO_CACHE或
SQL_CACHE提示,但 MySQL 8.0 已移除查询缓存,这类语句会被跳过日志记录 客户端连接设置了
long_query_time=0(会话级覆盖全局),但该会话后续又执行了
SET long_query_time=10,导致部分查询漏记
最隐蔽的一点:如果查询触发了隐式类型转换(比如
WHERE phone = 13800138000,而
phone是
VARCHAR),优化器可能放弃索引,但
query_time未必超限——这类问题不会出现在慢日志里,得靠
EXPLAIN或 Performance Schema 抓。
