2. 慢查询日志配置:MySQL慢查询日志开启、慢查询时间阈值设置、日志分析工具介绍
慢查询日志是数据库性能调优的“第一现场”。在Go项目上线后,如果某个接口响应突然变慢,第一件事就是检查慢查询日志——它记录了所有执行时间超过设定阈值的SQL语句,是定位数据库瓶颈最直接的证据。
2.1 慢查询日志的开启与配置
MySQL默认关闭慢查询日志,需要手动开启。以下是在线开启(无需重启)的推荐方式:
-- 开启慢查询日志(全局生效,重启后失效)
SET GLOBAL slow_query_log = ON;
-- 设置日志文件路径
SET GLOBAL slow_query_log_file = '/var/log/mysql/mysql-slow.log';
-- 设置慢查询时间阈值(单位:秒,推荐生产环境设为 0.5~1 秒)
SET GLOBAL long_query_time = 1;
-- 记录未使用索引的查询(强烈建议开启)
SET GLOBAL log_queries_not_using_indexes = ON;
生产建议: 如果希望重启后配置依然生效,请将上述参数写入
my.cnf 或 my.ini 的 [mysqld] 段。注意 long_query_time 支持小数,例如 0.5 表示500毫秒。
2.2 慢查询时间阈值设置策略
阈值设置过大会漏掉慢SQL,设置过小会产生大量日志影响磁盘I/O。不同场景的推荐值如下:
| 场景 | 推荐阈值 | 说明 |
|---|---|---|
| 高并发OLTP(如订单、支付) | 0.2 ~ 0.5 秒 | 要求单次查询极快,超过500ms即需关注 |
| 常规业务系统(如CMS、后台) | 1 ~ 2 秒 | 用户可接受1秒左右响应 |
| 离线分析/报表 | 5 ~ 10 秒 | 允许较长时间的数据聚合查询 |
| 开发/测试环境 | 0.1 ~ 0.3 秒 | 尽早暴露潜在慢查询 |
避坑: 不要在生产环境将
long_query_time 设为 0。这会记录所有查询,导致日志文件在几分钟内膨胀到GB级别,拖慢磁盘并影响MySQL性能。建议从 1 秒开始,逐步下调。
2.3 慢查询日志内容解读
一条典型的慢查询日志记录包含以下关键字段:
# Time: 2025-03-15T10:23:45.123456Z
# User@Host: go_app[go_app] @ [10.0.1.100] Id: 12345
# Query_time: 2.345678 Lock_time: 0.000123 Rows_sent: 1000 Rows_examined: 500000
SET timestamp=1742029425;
SELECT u.name, o.order_amount
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.created_at > '2025-01-01'
ORDER BY o.created_at DESC;
- Query_time:实际执行时间(秒),核心指标。
- Lock_time:锁等待时间,过高说明存在锁竞争。
- Rows_examined:扫描行数,远大于 Rows_sent 时说明索引缺失或查询计划不佳。
- SET timestamp:查询发起的时间戳,用于关联业务日志。
2.4 慢查询日志分析工具介绍
手动翻阅原始日志效率极低,必须借助工具进行聚合分析。以下是Go项目中最常用的三款工具:
| 工具 | 安装方式 | 核心能力 | 适用场景 |
|---|---|---|---|
| pt-query-digest | Percona Toolkit 自带 | 按查询指纹聚合、排序、输出执行计划建议 | 生产环境深度分析,最推荐 |
| mysqldumpslow | MySQL 自带 | 按平均时间/次数排序,输出TOP N | 快速查看最慢的几条SQL |
| Bytebase SQL 审核 | 独立部署或SaaS | 可视化慢查询看板、索引建议、历史趋势 | 团队协作、持续集成流程 |
实战命令示例:
该命令会生成一份按总耗时降序排列的报告,前几行就是需要优先优化的“头号慢查询”。
pt-query-digest /var/log/mysql/mysql-slow.log > slow_report.txt该命令会生成一份按总耗时降序排列的报告,前几行就是需要优先优化的“头号慢查询”。
2.5 慢查询日志分析流程(SVG)
下图展示了从日志采集到SQL优化的完整闭环流程,Go开发者应将其嵌入日常巡检SOP:
2.6 Go项目中的慢查询日志实践清单
- 统一日志路径:在
my.cnf中固定slow_query_log_file,便于自动化采集。 - 定时轮转:使用
logrotate按天或按大小切割日志,防止磁盘写满。 - 与APM联动:将慢查询日志中的
Query_time与Go应用的接口耗时做关联,快速定位是SQL慢还是业务逻辑慢。 - 灰度开启:先在预发布环境开启
log_queries_not_using_indexes,确认无副作用后再推至生产。
Go开发者专属提示: 在Go的数据库驱动(如
database/sql + go-sql-driver/mysql)中,可以通过设置 ?timeout=5s 连接参数实现应用层的超时保护,避免慢查询长时间阻塞goroutine。但这不能替代MySQL层面的慢查询日志——日志是事后分析的基础,超时是事中保护的手段,两者缺一不可。