本文承接MySQL运维系列内容,聚焦新手入门运维最刚需的两大核心日志:错误日志、慢查询日志 。
很多新手学习MySQL时,都会遇到两个最头疼的问题:一是MySQL启动失败、运行报错,完全不知道去哪找原因;二是SQL执行越来越慢,不知道哪条SQL拖垮了性能,无从下手优化。而解决这两个问题的核心钥匙,就是MySQL的日志。
错误日志是MySQL排障的第一入口,所有启动、运行、关闭的错误信息都会记录在这里,90%的MySQL启动失败、运行异常都能通过它1分钟定位原因;慢查询日志是SQL性能优化的核心工具,会自动记录所有执行超时的SQL,帮你精准找到拖慢系统的"坏SQL",是优化的第一手资料。
本文完全面向零基础新手,沿用系列统一的edu_shop电商库、edu_student学生管理库场景,用通俗的大白话、可直接复制的标准代码、真实业务排障实战,带你从零掌握两大日志的核心作用、配置方法、查看技巧、排障优化全流程,看完就能直接落地解决实际问题。
【前置必读】
- 本文所有示例基于MySQL 8.0 LTS版本,完全兼容MySQL 5.7,所有命令均经过实测可直接复制执行;
- 日志配置、查看分为两类操作,会明确标注执行环境:
- MySQL客户端内执行:Navicat、DBeaver、mysql> 命令行界面;
- 操作系统终端执行:Windows CMD/PowerShell、Linux Shell终端;
- 所有配置、查看操作均需要MySQL root超级管理员权限。
导言:先搞懂MySQL日志的核心价值
很多新手对MySQL日志的认知是"没用的日志文件,占磁盘空间",但实际上,日志是MySQL的"黑匣子",记录了MySQL从启动、运行到关闭的全生命周期行为,是排障、优化、审计的核心依据。
MySQL的日志体系分为6大类,新手入门优先吃透本文的2种核心日志即可,其他日志后续会逐步讲解:
- 错误日志(Error Log):本文核心,记录MySQL启动、运行、关闭过程中的错误、警告、关键事件,是排障的第一入口;
- 慢查询日志(Slow Query Log):本文核心,记录执行时间超过阈值的SQL语句,是SQL性能优化的核心工具;
- 二进制日志(Binlog):记录所有数据修改操作,用于数据恢复、主从复制,之前备份恢复文章已涉及;
- 重做日志(Redo Log):InnoDB引擎事务日志,用于崩溃恢复,保证数据持久性;
- 回滚日志(Undo Log):InnoDB引擎事务日志,用于事务回滚、MVCC多版本控制;
- 通用查询日志(General Log):记录所有客户端的连接和执行的SQL语句,日志量极大,生产环境默认关闭。
一、错误日志:MySQL排障的第一入口
错误日志是MySQL最核心的排障日志,没有之一。它就像MySQL的"病历本",记录了MySQL从启动、运行到关闭的所有异常信息、警告信息和关键生命周期事件,90%的MySQL启动失败、运行异常问题,都能通过错误日志1分钟定位根因。
1. 错误日志的核心作用
新手必须记住:只要MySQL启动失败、运行异常闪退、执行命令报错,第一时间就去看错误日志。它核心记录3类内容:
- 启动/关闭过程的关键信息:MySQL启动时的配置加载、端口监听、存储引擎初始化、关闭时的资源释放过程;
- 错误信息:启动失败、运行时的致命错误,比如端口被占用、数据文件损坏、权限不足、内存溢出等;
- 警告信息:非致命的风险提示,比如配置参数不兼容、密码过期、连接数超限等,提前规避潜在风险。
2. 第一步:找到错误日志的存储路径
新手最常见的问题:"我知道错误日志有用,但我不知道它在哪"。一条命令就能精准定位日志路径,在MySQL客户端内执行:
sql
-- 查看错误日志配置,核心看log_error的值,就是错误日志的完整路径
SHOW VARIABLES LIKE 'log_error%';
执行结果解读
| 变量名 | 示例值 | 含义 |
|---|---|---|
log_error |
/var/log/mysqld.log(Linux) D:\MySQL\log\mysqld.err(Windows) |
错误日志的完整存储路径+文件名 |
log_error_verbosity |
3 | 日志详细级别:1-只记录错误 2-错误+警告 3-错误+警告+信息(默认) |
不同系统的默认路径
- Linux系统 :默认路径通常是
/var/log/mysqld.log或/var/lib/mysql/主机名.err; - Windows系统 :默认在MySQL安装目录的
data文件夹下,文件名是主机名.err。
3. 错误日志的开启与配置
错误日志默认是开启的,无需手动开启,MySQL启动时就会自动生成并写入。如果需要自定义日志路径、调整日志级别,通过修改MySQL配置文件实现永久生效。
配置方法(永久生效)
- 找到MySQL的配置文件:
- Linux系统:
/etc/my.cnf或/etc/mysql/my.cnf; - Windows系统:MySQL安装目录下的
my.ini;
- Linux系统:
- 在配置文件的
[mysqld]节点下,添加/修改以下配置:
ini
[mysqld]
# 自定义错误日志存储路径,Linux示例
log_error = /var/log/mysql/mysqld.err
# Windows示例
# log_error = D:\MySQL\log\mysqld.err
# 日志详细级别,默认3即可,兼顾信息完整度和日志大小
log_error_verbosity = 3
- 保存配置文件,重启MySQL服务生效 :
- Linux:
systemctl restart mysqld - Windows:在服务面板重启MySQL服务
- Linux:
注意:自定义日志路径的文件夹必须提前创建,且给MySQL运行用户授予读写权限,否则MySQL会启动失败。
4. 错误日志的查看方法(新手可直接复制)
错误日志是纯文本文件,根据操作系统选择对应的查看方式,核心是过滤ERROR级别的错误信息,快速定位问题。
场景1:Linux系统查看(最常用,生产环境通用)
在Linux终端执行 ,核心用tail实时查看、grep过滤错误信息,新手记住以下3条命令即可覆盖90%的场景:
bash
# 1. 实时查看日志最新内容,排查启动失败、实时报错最常用(按Ctrl+C退出)
tail -f /var/log/mysqld.log
# 2. 查看日志最后100行,快速看最近的报错
tail -n 100 /var/log/mysqld.log
# 3. 过滤所有ERROR级别的错误信息,精准定位问题,最核心!
grep -i 'ERROR' /var/log/mysqld.log
# 4. 过滤指定时间段的错误信息,比如2024-06-01的报错
grep -i 'ERROR' /var/log/mysqld.log | grep '2024-06-01'
场景2:Windows系统查看
- 找到错误日志文件(.err后缀),用记事本、Notepad++、VS Code等文本编辑器直接打开;
- 用编辑器的查找功能,搜索
ERROR关键词,快速定位错误信息; - 实时查看可以用PowerShell的
Get-Content命令:
powershell
# Windows PowerShell实时查看错误日志,对应Linux的tail -f
Get-Content "D:\MySQL\log\mysqld.err" -Wait -Tail 100
5. 新手实战:用错误日志解决2个最常见的问题
实战1:MySQL启动失败,1分钟定位根因
问题现象 :Linux系统重启MySQL服务失败,systemctl start mysqld执行后提示启动失败,完全不知道哪里出了问题。
排障步骤:
- 执行命令查看错误日志的ERROR信息:
bash
grep -i 'ERROR' /var/log/mysqld.log | tail -n 20
- 查看报错结果,常见的3种报错与解决方案:
- 报错1:
Can't start server: Bind on TCP/IP port: Address already in use
根因:3306端口被其他程序占用,MySQL无法监听端口
解决方案:执行netstat -tulpn | grep 3306查看占用端口的程序,关闭占用程序,或修改MySQL端口后重启。 - 报错2:
Permission denied
根因:MySQL数据目录、日志目录的权限不对,MySQL运行用户没有读写权限
解决方案:给目录授予权限,执行chown -R mysql:mysql /var/lib/mysql/,重启服务。 - 报错3:
unknown variable 'xxx=xxx'
根因:my.cnf配置文件里有错误的参数,MySQL无法识别
解决方案:删除配置文件里的错误参数,保存后重启服务。
- 报错1:
实战2:MySQL运行警告,提前规避风险
问题现象 :MySQL能正常启动,但客户端连接时提示警告,或者业务偶尔出现连接超时。
排障步骤:
- 过滤错误日志中的WARNING警告信息:
bash
grep -i 'WARNING' /var/log/mysqld.log | tail -n 20
- 常见警告与解决方案:
- 警告1:
Too many connections
根因:连接数超过了MySQL的最大连接数限制,新的连接被拒绝
解决方案:修改配置文件的max_connections参数,调大最大连接数,同时检查业务是否有连接未释放的问题。 - 警告2:
Your password has expired
根因:用户密码过期,MySQL 8.0默认密码有有效期
解决方案:登录MySQL,执行ALTER USER '用户名'@'主机地址' IDENTIFIED BY '密码' PASSWORD EXPIRE NEVER;关闭密码过期。
- 警告1:
6. 错误日志使用避坑指南
- 绝对不要直接删除正在写入的错误日志文件 :Linux系统中,直接删除正在被MySQL写入的日志文件,会导致磁盘空间无法释放,正确做法是先清空日志
> /var/log/mysqld.log,或用日志轮转工具切割; - 定期归档清理日志:错误日志会持续增长,尤其是开启了详细级别后,建议配置logrotate(Linux)自动切割、归档、删除过期日志,避免占满磁盘空间;
- 生产环境不要关闭错误日志:哪怕MySQL运行稳定,也不要关闭错误日志,它是异常排障的唯一依据,关闭后出现问题将无据可查;
- 排障优先看最新的日志:错误日志是按时间顺序写入的,最新的报错在日志末尾,优先看最后几十行的内容,避免被历史报错干扰。
二、慢查询日志:SQL性能优化的核心工具
慢查询日志是MySQL专门用来记录"执行慢的SQL"的日志,它会按照你设置的时间阈值,自动记录所有执行超时的SQL语句,帮你精准定位拖垮数据库性能的"坏SQL",是SQL优化的第一步,也是最核心的一步。
很多新手遇到数据库变慢,只会盲目加索引、升级服务器,却不知道到底是哪条SQL慢、慢在哪里,而慢查询日志就是帮你找到优化目标的"导航仪"。
1. 慢查询日志的核心作用
- 精准定位慢SQL:自动记录所有执行时间超过阈值的SQL,不用你手动一条条排查;
- 还原执行上下文:记录SQL的执行时间、锁等待时间、扫描行数、返回行数,帮你分析SQL慢的根因;
- 性能优化的依据:通过分析慢日志,找到高频慢SQL,针对性优化,是数据库性能调优最核心的依据;
- 业务风险预警:通过慢日志的变化,提前发现业务代码的bug、索引失效、数据量暴涨带来的性能问题。
2. 慢查询日志核心配置参数(新手必记)
慢查询日志默认是关闭的,需要手动开启,核心配置参数如下,所有参数均可通过SHOW VARIABLES LIKE 'slow_query%';查看当前配置:
| 参数名 | 作用 | 推荐配置值 |
|---|---|---|
slow_query_log |
慢查询日志的开关:ON-开启 OFF-关闭 | 测试/生产环境均设为ON |
slow_query_log_file |
慢查询日志的完整存储路径+文件名 | Linux:/var/log/mysql/slow.log Windows:D:\MySQL\log\slow.log |
long_query_time |
慢查询阈值,单位:秒,SQL执行时间超过这个值就会被记录 | 生产环境推荐1,测试环境推荐0.5,最小可设为0 |
log_queries_not_using_indexes |
是否记录没用到索引的SQL,哪怕执行时间没超过阈值 | 测试环境推荐ON,生产环境按需开启(会增加日志量) |
log_throttle_queries_not_using_indexes |
限制每分钟记录的无索引SQL数量,避免日志暴涨 | 生产环境开启后设为60 |
min_examined_row_limit |
扫描行数少于这个值的SQL,不记录到慢日志,过滤无意义的小表查询 | 推荐1000 |
3. 慢查询日志的开启与配置
分为**临时配置(重启失效,适合测试)和永久配置(重启不失效,生产环境推荐)**两种方式。
方式1:临时配置(MySQL重启后失效)
适合测试环境快速开启验证,在MySQL客户端内执行:
sql
-- 1. 开启慢查询日志
SET GLOBAL slow_query_log = 'ON';
-- 2. 设置慢查询阈值为1秒,执行时间超过1秒的SQL会被记录
SET GLOBAL long_query_time = 1;
-- 3. 开启记录未使用索引的SQL
SET GLOBAL log_queries_not_using_indexes = 'ON';
-- 4. 限制每分钟无索引SQL的记录数量,避免日志暴涨
SET GLOBAL log_throttle_queries_not_using_indexes = 60;
-- 验证配置是否生效
SHOW VARIABLES LIKE 'slow_query%';
SHOW VARIABLES LIKE 'long_query_time';
注意:设置
long_query_time后,需要重新打开MySQL客户端会话才会生效,当前会话不会立即生效。
方式2:永久配置(重启不失效,生产环境推荐)
修改MySQL配置文件,永久生效,避免重启后配置丢失。
- 打开MySQL配置文件:Linux
/etc/my.cnf、Windowsmy.ini; - 在
[mysqld]节点下添加以下配置:
ini
[mysqld]
# 开启慢查询日志
slow_query_log = ON
# 慢查询日志存储路径,提前创建文件夹并授予MySQL读写权限
slow_query_log_file = /var/log/mysql/slow.log
# Windows示例
# slow_query_log_file = D:\MySQL\log\slow.log
# 慢查询阈值1秒
long_query_time = 1
# 记录未使用索引的SQL
log_queries_not_using_indexes = ON
# 限制每分钟无索引SQL的记录数量
log_throttle_queries_not_using_indexes = 60
# 扫描行数少于1000的SQL不记录,过滤小表查询
min_examined_row_limit = 1000
- 保存配置文件,重启MySQL服务生效:
systemctl restart mysqld(Linux)、Windows服务面板重启。
4. 慢查询日志的查看与分析方法
慢查询日志是纯文本文件,里面记录了每一条慢SQL的完整执行信息,新手可以先手动查看理解格式,再用官方工具批量分析。
第一步:理解慢查询日志的格式
我们先模拟一条慢SQL,看慢日志里记录了什么内容,在MySQL客户端执行:
sql
-- 模拟慢SQL,休眠3秒,一定会被记录到慢日志
SELECT SLEEP(3);
-- 用大表查询模拟真实慢SQL(基于之前的学生管理库)
SELECT * FROM edu_student WHERE address LIKE '%北京市%';
打开慢日志文件,会看到如下格式的内容,每一部分都有明确的含义:
# Time: 2024-06-01T10:00:00.123456Z -- SQL执行的时间
# User@Host: root[root] @ localhost [] -- 执行SQL的用户和客户端地址
# Query_time: 3.000215 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 1
-- 核心指标:
-- Query_time:SQL总执行时间,单位秒,就是我们的慢查询阈值判断依据
-- Lock_time:锁等待时间,单位秒
-- Rows_sent:返回给客户端的行数
-- Rows_examined:MySQL扫描的总行数,扫描行数远大于返回行数,说明需要加索引
SET timestamp=1717236000; -- SQL执行的时间戳
SELECT SLEEP(3); -- 执行的慢SQL语句
新手核心看3个指标:
Query_time:SQL执行时间,越长说明越慢,是优化的核心目标;Rows_examined和Rows_sent的差值:扫描行数远大于返回行数,说明SQL没有用到索引,全表扫描了大量数据,是优化的重点;Lock_time:锁等待时间过长,说明有事务锁冲突,需要排查并发写操作。
第二步:手动查看慢日志(新手入门)
和错误日志的查看方法一致,在操作系统终端执行:
bash
# Linux:实时查看慢日志最新内容
tail -f /var/log/mysql/slow.log
# Linux:查看日志最后50条慢SQL
tail -n 200 /var/log/mysql/slow.log
# Windows PowerShell:实时查看
Get-Content "D:\MySQL\log\slow.log" -Wait -Tail 100
第三步:用官方工具批量分析慢日志(生产环境必备)
慢日志里的SQL数量多了之后,手动查看根本不现实,MySQL自带了mysqldumpslow慢日志分析工具,无需额外安装,能快速对慢SQL进行分类、排序、统计,是新手分析慢日志的首选工具。
1. 核心语法
bash
mysqldumpslow [参数] 慢日志文件路径
2. 新手必学的常用参数
| 参数 | 作用 |
|---|---|
-s t |
按SQL总执行时间排序(默认),找最慢的SQL |
-s c |
按SQL执行次数排序,找高频执行的慢SQL |
-s l |
按锁等待时间排序,找锁冲突严重的SQL |
-s r |
按扫描行数排序,找全表扫描最严重的SQL |
-t N |
只显示前N条结果 |
-g 关键词 |
过滤包含指定关键词的SQL |
3. 实战常用命令(可直接复制)
bash
# 1. 查看执行时间最慢的前10条SQL,最常用!
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
# 2. 查看执行次数最多的前10条高频慢SQL
mysqldumpslow -s c -t 10 /var/log/mysql/slow.log
# 3. 查看扫描行数最多的前10条SQL,找全表扫描的坏SQL
mysqldumpslow -s r -t 10 /var/log/mysql/slow.log
# 4. 过滤包含edu_order订单表的慢SQL
mysqldumpslow -g 'edu_order' /var/log/mysql/slow.log
4. 分析结果解读
执行命令后,会返回分类统计后的结果,示例如下:
Count: 5 Time=2.56s (12.8s) Lock=0.00s Rows=100.0 (500), root[root]@localhost
SELECT * FROM edu_order WHERE user_id = N;
Count:5:这条SQL一共执行了5次;Time=2.56s (12.8s):单次平均执行时间2.56秒,总执行时间12.8秒;Rows=100.0 (500):单次平均返回100行,总返回500行;N:mysqldumpslow会把数字、字符串自动替换为N,把相同模板的SQL合并统计,避免重复。
5. 新手实战:慢查询日志从开启到优化的完整闭环
我们用之前的电商库edu_shop,走一遍完整的慢查询优化流程,新手可以跟着同步操作。
步骤1:开启慢查询日志,设置阈值0.5秒
sql
-- 临时开启慢查询
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 0.5;
SET GLOBAL log_queries_not_using_indexes = 'ON';
-- 重新打开客户端会话,确认配置生效
SHOW VARIABLES LIKE 'slow_query_log';
步骤2:模拟业务慢SQL
sql
-- 1. 全表扫描查询北京市的用户,无索引,执行慢
SELECT * FROM edu_user WHERE address LIKE '%北京市%';
-- 2. 联表查询用户的订单,无合适索引
SELECT u.username, o.order_no, o.pay_amount, o.create_time
FROM edu_user u
LEFT JOIN edu_order_main o ON u.user_id = o.user_id
WHERE u.province = '广东省';
-- 3. 统计订单金额,无索引
SELECT SUM(pay_amount) FROM edu_order_main WHERE create_time BETWEEN '2024-05-01' AND '2024-06-01';
步骤3:用mysqldumpslow分析慢日志
bash
# 查看执行时间最慢的前5条SQL
mysqldumpslow -s t -t 5 /var/log/mysql/slow.log
步骤4:根据分析结果优化SQL
根据慢日志的Rows_examined指标,发现3条SQL都是全表扫描,没有用到索引,针对性添加索引:
sql
-- 1. 给用户表的省份字段加索引
ALTER TABLE edu_user ADD INDEX idx_province (province);
-- 2. 给订单表的user_id加索引(联表字段必须加索引)
ALTER TABLE edu_order_main ADD INDEX idx_user_id (user_id);
-- 3. 给订单表的创建时间加索引
ALTER TABLE edu_order_main ADD INDEX idx_create_time (create_time);
步骤5:验证优化效果
重新执行之前的SQL,查看执行时间,会发现执行时间从几秒降到了几毫秒,不再出现在慢查询日志中,优化完成。
6. 慢查询日志使用避坑指南
- 生产环境不要把long_query_time设为0:会记录所有执行的SQL,导致日志文件暴涨,很快占满磁盘空间,生产环境最小设为0.1秒,推荐1秒;
- 生产环境开启log_queries_not_using_indexes要谨慎 :如果有大量小表全表查询,会导致日志量暴增,建议配合
log_throttle_queries_not_using_indexes限制记录数量; - 定期归档清理慢日志:慢日志会持续增长,建议配置logrotate自动切割归档,避免占满磁盘;
- 不要直接在生产环境用文本编辑器打开大的慢日志文件:几个G的日志文件直接打开会导致服务器卡顿,用mysqldumpslow工具分析即可;
- 慢日志分析要关注高频慢SQL,而不是单次最慢的SQL:一条单次执行10秒的SQL,对系统的影响远不如一条每次执行0.5秒、每分钟执行1000次的高频慢SQL,优化优先看执行次数多的SQL。
三、生产环境日志管理最佳实践
- 统一日志存储路径:把错误日志、慢查询日志、binlog都放在统一的日志目录下,不要分散在数据目录,方便管理、备份和权限控制;
- 配置日志自动轮转:Linux系统用logrotate工具,Windows系统用定时任务,自动切割、压缩、归档、删除过期日志,避免日志文件过大、占满磁盘空间;
- 定期分析日志:每周至少分析一次慢查询日志,优化高频慢SQL;每天巡检错误日志,提前发现潜在的风险警告,不要等出了问题才去看日志;
- 日志权限管控:日志文件只能给MySQL运行用户和root用户读写权限,禁止其他用户访问,避免日志中的敏感信息(SQL、用户信息)泄露;
- 测试环境和生产环境配置一致:测试环境开启慢查询日志,阈值设得更低,在测试阶段就发现并优化慢SQL,不要等到生产环境出了性能问题才优化。
四、新手高频报错与解决方案
1. 开启慢查询日志后,slow_query_log还是OFF
原因 :慢日志路径的文件夹不存在,或者MySQL没有读写权限,导致开启失败。
解决方案:
- 手动创建日志文件夹,比如
mkdir -p /var/log/mysql/; - 给文件夹授予MySQL权限:
chown -R mysql:mysql /var/log/mysql/; - 重新执行开启命令,或重启MySQL服务。
2. 设置了long_query_time=1,但所有SQL都不被记录
原因 :设置GLOBAL参数后,当前会话不会生效,需要重新打开MySQL客户端会话;或者SQL执行时间确实没有超过阈值。
解决方案 :重新打开Navicat、mysql命令行等客户端,重新执行SQL,或用SELECT SLEEP(2);模拟慢SQL验证。
3. 错误日志里没有内容,启动失败也看不到报错
原因 :自定义了错误日志路径,但文件夹不存在或权限不对,MySQL无法写入日志,只能把报错输出到系统日志。
解决方案:
- Linux:查看系统日志
/var/log/messages或journalctl -u mysqld,找到启动失败的原因; - Windows:查看系统事件查看器里的MySQL错误信息;
- 修复日志路径的权限和文件夹,重启MySQL服务。
4. mysqldumpslow命令执行提示"未找到命令"
原因 :MySQL的bin目录没有添加到系统环境变量,和之前mysqldump命令的问题一致。
解决方案:
- 进入MySQL安装目录的bin文件夹下执行命令;
- 把MySQL的bin目录添加到系统环境变量,永久生效。
结语
错误日志和慢查询日志,是MySQL新手入门运维的两大核心工具,一个帮你解决"MySQL能不能跑起来"的问题,一个帮你解决"MySQL跑得快不快"的问题。
很多新手觉得运维很难,其实绝大多数的数据库问题,都能通过这两个日志找到答案。不用追求复杂的监控工具,先把这两个基础日志吃透,养成"出问题先看日志,优化先看慢查询"的习惯,你的MySQL运维能力就已经超过了80%的新手。
需要我给你一份Linux系统的logrotate日志轮转配置模板,自动切割错误日志和慢查询日志,避免磁盘占满吗?