慢查询定位的基本思路
业务变慢时,数据库侧要回答的是「哪条语句慢、为什么慢、慢在等待还是慢在扫描」。开启慢查询日志能拿到语句清单,查看当前会话能看到正在执行的语句与等待状态,执行计划则解释优化器选择了全表扫描还是索引访问。三步合起来才能定位根因。
慢不一定全在数据库
应用侧连接池排队、锁等待、存储层抖动都会把响应时间放大。看到数据库指标正常但业务仍慢时,需要把耗时拆解到各环节:应用日志的时间戳、数据库会话的执行时间、存储的响应延迟。缺少分段数据,很容易把存储问题记到数据库账上。
基本信息
| 慢日志参数 | 是否开启、阈值、日志文件路径 |
|---|---|
| 实时观察 | 当前进程列表、事务与锁等待信息 |
| 执行计划 | 查看访问类型、扫描行数与额外信息 |
| 临时缓解 | 并发限流、批任务错峰、必要时加索引 |
典型使用场景
- 业务反馈页面响应变慢,需要确认是否由慢语句造成
- 批任务与在线业务并发时性能下降,需要错峰
- 上线新功能后数据库负载明显升高
- 迁移到新平台后同样的语句执行时间变长
- 容量评估阶段梳理慢语句并制定优化清单
找慢语句(示例)
找慢语句(示例)
mysql -uroot -p -e "SHOW VARIABLES LIKE 'slow_query_log%'"
mysql -uroot -p -e "SHOW VARIABLES LIKE 'long_query_time'"
mysql -uroot -p -e 'SHOW FULL PROCESSLIST' | head -30
mysql -uroot -p -e 'SHOW ENGINE INNODB STATUS' | head -40 # 锁与事务线索执行计划与缓解
执行计划与缓解
mysql -uroot -p -e 'EXPLAIN <慢SQL>' # 关注访问类型、扫描行数与额外信息
# 全表扫描是常见根因:与研发确认是否有可用索引或能否改写语句
# 临时缓解:对相关业务限流、把批任务挪到业务低峰
# 变更索引前先在测试库评估写入开销与存储占用证据与含义
| 证据 | 含义 | 方向 |
|---|---|---|
| 慢日志条目 | 超过阈值的语句 | 按出现频次排序后优先处理 |
| 会话状态为等待 | 在等锁或等 IO | 查锁等待与存储延迟 |
| 事务长时间未提交 | 长事务阻塞其他会话 | 与研发约定期限并拆分 |
| 连接池等待计数升高 | 应用侧连接不足 | 调整池容量或缩短语句耗时 |
| 扫描行数远大于返回行数 | 索引效率低 | 评估索引与语句改写 |
慢查询日志本身有写入开销,建议在业务低峰短时开启,问题定位清楚后按需关闭。开启期间注意日志目录的空间,避免排查过程把磁盘写满。