说明:标题中的MySQL 8.1在本文写作时(2023年4月)尚未发布(MySQL 8.1于2023年7月发布)。
本文基于我排查MySQL线上Bug的真实经历,分享排查过程、问题原因、解决方法,以及经验教训。
一、问题出现
1. 报警了
那天晚上,报警了。
- 接口响应慢
- 数据库连接数飙升
- CPU使用率高
- 慢查询告警
- 我被电话叫醒了
线上问题,总是在半夜来。
2. 初步判断
初步判断:
- 是数据库的问题
- 不是应用的问题
- 某个SQL特别慢
- 导致连接堆积
- 需要尽快找到原因
数据库,是瓶颈。
3. 开始排查
我开始排查。
- 登录服务器
- 看MySQL状态
- 看慢查询日志
- 看进程列表
- 一步步来
排查,需要冷静。
二、排查过程
1. 第一步:看进程列表
第一步:看进程列表。
SHOW PROCESSLIST;- 发现很多查询在等待
- 状态是"Sending data"
- 有一个查询特别慢
- 已经跑了几分钟
- 找到了元凶
慢查询,是罪魁祸首。
2. 第二步:看慢查询日志
第二步:看慢查询日志。
# 查看慢查询配置
SHOW VARIABLES LIKE 'slow_query%';
# 查看慢查询日志
tail -f /var/log/mysql/slow.log- 找到了那个慢SQL
- 是一个联表查询
- 扫描了几百万行
- 没有走索引
- 问题找到了
慢查询日志,是线索。
3. 第三步:EXPLAIN分析
第三步:EXPLAIN分析。
EXPLAIN SELECT ... FROM table1
JOIN table2 ON ...
WHERE ...;- type是ALL
- 全表扫描
- rows是几百万
- Extra是Using where
- 确认没有走索引
EXPLAIN,是诊断工具。
4. 第四步:看索引
第四步:看索引。
SHOW INDEX FROM table1;
SHOW INDEX FROM table2;- 发现WHERE条件的字段没有索引
- JOIN的字段也没有索引
- 难怪慢
- 需要加索引
索引缺失,是根本原因。
5. 第五步:为什么之前没问题
第五步:为什么之前没问题。
- 这个SQL一直存在
- 之前跑得好好的
- 为什么突然慢了?
- 看了一下数据量
- 最近数据暴涨
- 索引不够用了
数据增长,是导火索。
三、解决问题
1. 临时方案:Kill慢查询
临时方案:Kill慢查询。
KILL <process_id>;- 先把慢查询杀掉
- 让系统恢复
- 再慢慢优化
- 先止血,再治病
止血,是第一步。
2. 加索引
加索引:
ALTER TABLE table1 ADD INDEX idx_field1 (field1);
ALTER TABLE table2 ADD INDEX idx_field2 (field2);- 给WHERE条件加索引
- 给JOIN字段加索引
- 加完之后
- 查询从几秒变成几毫秒
索引,是解药。
3. 优化SQL
优化SQL:
- 原来的SQL写得不好
- 子查询嵌套
- 改成JOIN
- 只查需要的字段
- 性能又提升了
SQL优化,是根本。
4. 验证
验证:
- 加完索引后测试
- EXPLAIN看执行计划
- type变成ref
- rows变成几十
- 性能提升明显
验证,确保有效。
四、为什么会发生
1. 原因一:索引缺失
第一个原因:索引缺失。
- 设计表的时候
- 没有考虑到这个查询
- 没有加索引
- 数据量小的时候没问题
- 数据量大了就慢了
索引设计,要提前考虑。
2. 原因二:数据增长
第二个原因:数据增长。
- 业务发展快
- 数据量暴涨
- 原来的设计不够用了
- 没有提前扩容
- 没有定期优化
数据增长,是常态。
3. 原因三:没有监控
第三个原因:没有监控。
- 没有慢查询监控
- 没有索引使用监控
- 问题积累到爆发才发现
- 应该提前发现
- 提前优化
监控,是预防。
4. 原因四:代码质量
第四个原因:代码质量。
- SQL写得不规范
- 没有代码审查
- 烂SQL上线了
- 埋下了隐患
- 迟早出问题
代码质量,是基础。
五、经验教训
1. 教训一:索引很重要
第一个教训:索引很重要。
- 索引是数据库性能的关键
- 设计表的时候就要考虑
- 定期检查索引使用情况
- 删除无用索引
- 添加缺失索引
索引,是数据库的生命线。
2. 教训二:监控要完善
第二个教训:监控要完善。
- 慢查询监控
- 连接数监控
- CPU监控
- 磁盘监控
- 告警要及时
监控,是眼睛。
3. 教训三:定期优化
第三个教训:定期优化。
- 定期检查慢查询
- 定期优化SQL
- 定期整理索引
- 定期归档数据
- 不要等出问题才优化
定期优化,是习惯。
4. 教训四:代码审查
第四个教训:代码审查。
- SQL也要审查
- 看执行计划
- 看索引使用
- 烂SQL不要上线
- 从源头避免问题
代码审查,是防线。
5. 教训五:备份和回滚
第五个教训:备份和回滚。
- 操作前备份
- 加索引前测试
- 有回滚方案
- 出问题能快速恢复
- 不要裸操作
备份,是最后的保障。
六、排查技巧
1. 技巧一:保持冷静
第一个技巧:保持冷静。
- 线上问题不要慌
- 慌了容易出错
- 一步步来
- 先止血再优化
- 冷静才能解决问题
冷静,是最重要的素质。
2. 技巧二:先看状态
第二个技巧:先看状态。
- SHOW PROCESSLIST
- SHOW STATUS
- 看整体状态
- 再定位具体问题
- 不要一上来就改
先看状态,再动手。
3. 技巧三:用对工具
第三个技巧:用对工具。
- EXPLAIN
- 慢查询日志
- performance_schema
- 监控系统
- 工具能帮你快速定位
工具,是效率的倍增器。
4. 技巧四:记录过程
第四个技巧:记录过程。
- 排查的时候记录
- 做了什么
- 结果是什么
- 方便事后复盘
- 方便团队分享
记录,是成长的开始。
5. 技巧五:事后复盘
第五个技巧:事后复盘。
- 问题解决后复盘
- 根因是什么
- 怎么避免
- 流程怎么改进
- 不要白踩坑
复盘,是进步的阶梯。
七、预防措施
1. 措施一:建立慢查询告警
第一个措施:建立慢查询告警。
- 超过1秒的SQL告警
- 及时发现
- 及时优化
- 不要等堆积
告警,是预警。
2. 措施二:定期索引审计
第二个措施:定期索引审计。
- 每月检查索引
- 删除无用索引
- 添加缺失索引
- 优化索引结构
审计,是维护。
3. 措施三:SQL上线审查
第三个措施:SQL上线审查。
- 新SQL必须审查
- 看执行计划
- 看索引使用
- 烂SQL不上线
审查,是把关。
4. 措施四:数据归档
第四个措施:数据归档。
- 历史数据归档
- 保持表数据量合理
- 分区表
- 冷热分离
归档,是减负。
5. 措施五:压测
第五个措施:压测。
- 上线前压测
- 模拟大流量
- 发现性能瓶颈
- 提前优化
压测,是保险。
八、写在最后
线上出了个MySQL的Bug,我排查了一夜。
问题是索引缺失导致的慢查询,数据增长后爆发。排查过程:看进程列表、看慢查询日志、EXPLAIN分析、看索引、找到原因。解决方法:Kill慢查询止血、加索引、优化SQL、验证。经验教训:索引很重要、监控要完善、定期优化、代码审查、备份和回滚。
2023年了,数据库依然是系统的核心,也是最容易出问题的地方。线上问题不可怕,可怕的是不从问题中学习。每次排查,都是一次成长。建立完善的监控和流程,才能减少问题的发生。
最后,用一句话总结:"线上Bug不可怕,可怕的是不总结。每次排查都是一次学习,建立流程,预防为主,才能少熬夜。"
愿你少遇到线上Bug,遇到了也能从容应对。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录