很多做后端开发、运维或者数据库管理的人,遇到"MySQL 出问题了"时,第一反应往往是"重启试试"或者"翻代码"。但真正定位问题最快的方式,其实是先看日志。我自己的习惯是:任何数据库异常,先花 5 分钟翻日志,通常就能确定七八成的方向。别说你从没看过,很多人所谓的"看日志",其实就是打开错误日志文件拖到最后看两眼,这完全不够。
这篇我系统梳理一下 MySQL 日志体系的完整查看方法,从错误日志、通用查询日志、慢查询日志到 binlog,把在哪里看、怎么看、看完怎么用讲清楚。文章覆盖 MySQL 5.7 和 8.0 两个主流版本,面向从没碰过日志的新手,也面向想看深一点的进阶者。内容全部基于我实际踩过的坑和日常运维经验,直接照着操作就行。
1. MySQL 日志体系全景:先搞清楚到底有哪些日志
很多人觉得 MySQL 日志就是"日志"两个字,其实 MySQL 的日志体系有五大类,职责完全不同。不看日志可能还好,一旦需要排查问题,搞混日志类型是最大的坑。
1.1 五大日志类型及职责划分
- 错误日志(error log):记录 MySQL 启动、运行、停止过程中的关键事件和错误信息。比如配置文件加载失败、InnoDB 崩溃恢复、权限问题、端口被占用。排查启动失败和严重故障时最先看。
- 通用查询日志(general query log):记录客户端所有的 SQL 语句和连接/断开事件。信息最全但性能开销巨大,生产环境默认关闭,只有在调试特定应用问题或追踪恶意 SQL 时才临时开启。
- 慢查询日志(slow query log):记录执行时间超过阈值的 SQL 语句,以及未使用索引的查询。这是优化 SQL 性能的第一利器,也是排查接口响应慢、数据库 CPU 飙升的重要依据。
- 二进制日志(binlog):记录所有引起数据变更的事件(INSERT、UPDATE、DELETE 等),用于主从复制和数据恢复。这是数据安全的重要保障。
- 事务日志(redo log + undo log):这两个属于 InnoDB 存储引擎内部日志,redo log 保证崩溃后数据不丢(crash recovery),undo log 用于事务回滚和 MVCC 多版本控制。平时主要通过
SHOW ENGINE INNODB STATUS和性能监控间接查看,很少直接读文件。
1.2 各日志类型快速对比表
| 日志类型 | 主要用途 | 默认状态 | 查看难度 | 对性能影响 |
|---|---|---|---|---|
| 错误日志 | 启动故障、运行错误 | 开启 | 容易 | 极小 |
| 通用查询日志 | 完整 SQL 审计跟踪 | 关闭 | 容易 | 极大,生产慎开 |
| 慢查询日志 | SQL 性能优化 | 关闭(5.7 后部分默认开) | 较易 | 低 |
| 二进制日志 | 复制、恢复 | 取决于配置 | 中等 | 中等 |
| redo/undo | InnoDB 内部机制 | 自动管理 | 困难(间接查看) | 无额外影响 |
我的建议很简单:错误日志时刻都要看,慢查询日志一定要开,binlog 必须配好,通用查询日志只在紧急排查时临时用。搞清楚每类日志的定位,后面查问题就不会抓瞎。
2. 核心查看方法实战:命令与文件操作详解
先说说日志文件在哪里。我用过的生产环境里,日志路径五花八门——有人放在/var/log/mysql/,有人放在 MySQL 数据目录下,还有人自定义路径。与其猜,不如先用 SQL 查。进入 MySQL 命令行客户端,执行:
SHOW VARIABLES LIKE 'log_error'; SHOW VARIABLES LIKE 'general_log_file'; SHOW VARIABLES LIKE 'slow_query_log_file';这是一个非常核心的思路:用一个统一的"查变量"的方式,去确认当前实例所有日志的真实路径,比记忆默认路径可靠得多。我之前接手一个项目,前一个 DBA 把日志目录指到了/home/mysql/logs,如果按照默认路径去找,永远看不到任何日志。
2.1 错误日志:启动异常和运行故障的第一现场
错误日志是排查一切问题的基础。当 MySQL 启动失败、出现未知异常、主从切换失败等突发情况时,第一件事必须是看错误日志。
查看方式一:SQL 查询变量确认路径
-- 查看错误日志路径 SHOW VARIABLES LIKE 'log_error'; -- 查看错误日志是否开启(MySQL 5.7 后) SHOW GLOBAL VARIABLES LIKE 'log_error_verbosity';log_error_verbosity参数控制日志的详细程度,值有 1、2、3。1 只记录错误信息,2 记录错误和警告,3 最详细,还会记录一些注意级信息。排查问题期间建议临时调到 3,能获得更多线索,排查完记得调回 2,因为最详细级别在极端情况下也会刷大量日志,占用磁盘。
查看方式二:直接用系统命令读取文件
日志文件本质就是文本文件,Linux 下用习惯的tail命令:
# 查看最后 50 行错误日志 tail -n 50 /var/log/mysql/error.log # 持续跟踪输出最新日志(类似实时滚动) tail -f /var/log/mysql/error.log # 按关键字过滤 grep -i "error" /var/log/mysql/error.log # 分页查看完整内容 less /var/log/mysql/error.log我是一个特别爱用tail -f的人。比如启动 MySQL 遇到问题,我会开一个终端窗口,先执行tail -f /var/log/mysql/error.log,然后另一个终端执行systemctl start mysqld,启动过程中的所有失败原因都会实时滚动出来。这样排查启动问题效率极高,一次就能看到报错的前因后果,比反复重启反复翻日志强太多了。
注意:生产环境执行
tail -f之前,先确认你的 SSH 终端不会断连。如果连接不稳定,建议用screen或tmux工具开一个会话,防止断连导致终端卡死,特别是长时间观察日志的场景。
2.2 通用查询日志:什么 SQL 都逃不过的眼睛
通用查询日志会把每一个连接上来的客户端执行的每一条 SQL 原样记录下来,包括只读的 SELECT、事务的 BEGIN 和 COMMIT,甚至连接和断开本身也被记录。它的作用是已知问题需要复现、捕获应用发出的具体 SQL 语句时很有价值,代价是写入量大。
开启方法(临时开启,排查完务必关闭):
-- 查看当前状态 SHOW VARIABLES LIKE 'general_log'; -- 开启通用查询日志(动态生效,不需重启) SET GLOBAL general_log = 'ON'; -- 查看输出文件路径 SHOW VARIABLES LIKE 'general_log_file';开启后,应用产生的所有 SQL 都会实时写入general_log_file指定的文件。我之前排查过一个诡异问题:线上有个接口偶发超时,代码里明明没写慢 SQL,但就是偶发卡顿。后来临时开启通用查询日志才发现,某个定时任务每 5 分钟会执行一次全表扫描的SELECT COUNT(*) FROM huge_table,跟正常业务的 SQL 挤在一起,导致偶发锁竞争。不开通用日志,这种会话级别的偶发问题几乎不可能定位。
查看方式:
# 实时跟踪通用查询日志 tail -f /path/to/general.log # 查看某个客户端 IP 的相关 SQL grep "192.168.1.100" /path/to/general.log # 查看包含特定表名的查询 grep "SELECT \* FROM orders" /path/to/general.log使用禁忌:
- 生产环境不要长时间开启。通用查询日志的写入开销远超想象,我之前测试过一个 MySQL 8.0 实例,开启后 TPS 直接下降 20% 左右,在低配机器上更严重。
- 用完立刻关闭:
SET GLOBAL general_log = 'OFF'; - 千万别忘了清空日志文件。如果文件已经变得特别大,先
SET GLOBAL general_log = 'OFF',再清空文件或删除重建,最后重新开启。
2.3 慢查询日志:SQL 性能优化最实用的日志
慢查询日志是 DBA 和开发者日常接触最多的性能日志。它的核心价值在于直接告诉