2、MySQL慢查询基础:慢查询日志的开启与配置、慢查询日志的格式解读、使用mysqldumpslow分析日志
在Go项目连接池调优之前,必须先建立慢查询监控能力。MySQL慢查询日志是定位低效SQL最直接的工具,它记录了执行时间超过指定阈值的所有SQL语句。本章将系统讲解慢查询日志的开启配置、日志格式解析以及使用官方工具mysqldumpslow进行聚合分析的方法。
2.1 慢查询日志的开启与配置
MySQL默认关闭慢查询日志,需要手动启用。推荐在my.cnf配置文件中进行持久化设置,避免重启后失效。
2.1.1 核心配置参数
| 参数名 | 默认值 | 说明 |
|---|---|---|
slow_query_log |
OFF |
是否开启慢查询日志,设为1或ON开启 |
slow_query_log_file |
hostname-slow.log |
慢查询日志文件路径,建议指定绝对路径 |
long_query_time |
10.000000 |
SQL执行时间超过此值(秒)才记录,生产环境建议设为1或0.5 |
log_queries_not_using_indexes |
OFF |
是否记录未使用索引的查询,调优时建议开启 |
log_slow_admin_statements |
OFF |
是否记录慢管理语句(如ALTER TABLE、ANALYZE TABLE) |
min_examined_row_limit |
0 |
扫描行数超过此值才记录,可用于过滤小表全表扫描 |
2.1.2 配置文件示例
在my.cnf的[mysqld]段添加以下配置:
[mysqld]
# 开启慢查询日志
slow_query_log = 1
# 日志文件路径,确保MySQL用户有写入权限
slow_query_log_file = /var/log/mysql/mysql-slow.log
# 阈值:超过1秒即记录
long_query_time = 1
# 记录未使用索引的查询
log_queries_not_using_indexes = 1
# 记录慢管理语句
log_slow_admin_statements = 1
# 扫描行数超过1000行才记录(可选过滤)
min_examined_row_limit = 1000
生产建议:在Docker容器中运行MySQL时,建议将慢查询日志挂载到宿主机目录,便于集中采集和分析。同时注意日志文件可能快速增长,建议配置日志轮转(如
logrotate)或定期清理。
2.1.3 运行时动态修改
无需重启MySQL,可通过SET GLOBAL命令在线调整:
-- 开启慢查询日志
SET GLOBAL slow_query_log = ON;
-- 设置阈值1秒
SET GLOBAL long_query_time = 1;
-- 查看当前配置
SHOW VARIABLES LIKE 'slow_query_log%';
SHOW VARIABLES LIKE 'long_query_time';
注意:
long_query_time的修改仅对新连接生效,已存在的连接仍使用旧值。建议在修改后重新建立数据库连接,或通过连接池刷新连接。
2.2 慢查询日志的格式解读
理解慢查询日志的每一行含义,是精准定位性能瓶颈的前提。以下是一条典型的慢查询日志记录:
# Time: 2025-03-15T10:23:45.123456Z
# User@Host: go_app[go_app] @ [172.17.0.3] Id: 12345
# Query_time: 2.345678 Lock_time: 0.000123 Rows_sent: 50 Rows_examined: 50000
# Thread_id: 12345 Schema: ecommerce Last_errno: 0 Killed: 0
# Query_time distribution:
# 1% in 0.1s to 0.5s
# 99% in 2.0s to 5.0s
SET timestamp=1742027025;
SELECT o.id, o.total_amount, u.name
FROM orders o
JOIN users u ON o.user_id = u.id
WHERE o.status = 'pending'
ORDER BY o.created_at DESC
LIMIT 50;
2.2.1 日志字段解析
| 字段 | 示例值 | 含义 |
|---|---|---|
Time |
2025-03-15T10:23:45.123456Z |
SQL执行结束的时间戳(UTC) |
User@Host |
go_app[go_app] @ [172.17.0.3] |
执行SQL的用户名、主机名和客户端IP |
Query_time |
2.345678 |
SQL实际执行时间(秒),核心关注指标 |
Lock_time |
0.000123 |
等待表锁或行锁的时间(秒) |
Rows_sent |
50 |
返回给客户端的行数 |
Rows_examined |
50000 |
MySQL为执行查询扫描的行数 |
Thread_id |
12345 |
执行该SQL的线程ID |
Schema |
ecommerce |
当前使用的数据库名 |
SET timestamp |
1742027025 |
SQL执行开始时间的Unix时间戳 |
关键指标解读:
- Query_time:直接反映SQL性能,超过
long_query_time阈值即被记录。 - Rows_examined / Rows_sent:比值过大(如1000:1)通常表示缺少索引或查询条件不精确。
- Lock_time:过高可能暗示锁竞争,需要检查事务隔离级别或并发写操作。
2.3 使用mysqldumpslow分析日志
原始慢查询日志包含大量重复SQL(仅参数不同),手动分析效率极低。mysqldumpslow是MySQL官方提供的日志聚合工具,能将相似的SQL归并统计,输出排名靠前的“慢查询模式”。
2.3.1 基本语法
mysqldumpslow [options] [log_file ...]
2.3.2 常用选项
| 选项 | 说明 | 示例 |
|---|---|---|
-s |
排序方式:t(按查询时间)、c(按计数)、l(按锁时间)、r(按返回行数) |
-s t |
-t |
只显示前N条 | -t 10 |
-g |
正则过滤SQL内容 | -g "SELECT.*orders" |
-a |
不将数字抽象为N,显示原始值 |
-a |
--verbose |
详细输出 | --verbose |
2.3.3 典型使用场景
场景1:查看耗时最长的前5条SQL
mysqldumpslow -s t -t 5 /var/log/mysql/mysql-slow.log
场景2:查看出现次数最多的前10条SQL
mysqldumpslow -s c -t 10 /var/log/mysql/mysql-slow.log
场景3:过滤出涉及orders表的慢查询
mysqldumpslow -g "orders" /var/log/mysql/mysql-slow.log
2.3.4 输出示例解读
Count: 123 Time=2.34s (288s) Lock=0.00s (0s) Rows=50.0 (6150), go_app[go_app]@[172.17.0.3]
SELECT o.id, o.total_amount, u.name
FROM orders o
JOIN users u ON o.user_id = u.id
WHERE o.status = 'N'
ORDER BY o.created_at DESC
LIMIT N
| 聚合字段 | 值 | 含义 |
|---|---|---|
Count |
123 |
该模式SQL共执行了123次 |
Time=2.34s (288s) |
平均2.34秒,总耗时288秒 | 平均执行时间 / 括号内为累计总时间 |
Lock=0.00s (0s) |
平均锁等待0秒 | 锁竞争不严重 |
Rows=50.0 (6150) |
平均返回50行,累计返回6150行 | 每次返回行数稳定 |
分析技巧:优先关注
Count高且Time大的SQL,它们对系统总负载影响最大。如果Rows_examined远大于Rows_sent,应检查索引是否缺失或查询条件是否需要优化。
2.4 慢查询日志分析流程(SVG)
下图展示了从开启日志到定位慢SQL的完整工作流:
2.5 慢查询日志与连接池性能的关系
在Go项目中,慢查询会直接影响连接池的行为:
- 连接占用时间变长:一条慢查询执行2秒,意味着该连接在这2秒内无法被其他请求复用,导致连接池有效连接数减少。
- 连接池排队加剧:当慢查询比例升高,连接池中的连接被长时间占用,新请求必须等待空闲连接,造成请求排队和超时。
- 连接池扩容误判:如果监控系统看到连接池使用率上升,可能触发扩容策略,但实际是慢查询导致连接周转变慢,而非流量增长。
调优原则:在调整连接池参数(如
MaxOpenConns、MaxIdleConns)之前,必须先通过慢查询日志消除或减少慢SQL。否则,连接池调优只能缓解症状,无法根治性能问题。
2.6 本章小结
- 慢查询日志是MySQL性能调优的第一道防线,必须正确开启和配置。
- 日志中的
Query_time、Rows_examined、Rows_sent是核心分析指标。 mysqldumpslow工具能快速聚合日志,输出排名靠前的慢查询模式。- 慢查询与连接池性能强相关:慢SQL会降低连接复用率,加剧连接池竞争。