> 本文由 苏州市天智教育培训中心 技术团队整理,基于真实生产故障复盘,面向一线运维与开发同学,可直接用于排障参考。
一、问题现象
业务整体变慢,数据库 CPU 冲到 100%。慢日志里同一条 SQL 反复出现,执行时间十几秒。开发说"SQL 没变过",但数据量变了。
二、排查思路速览
先按下面的路径走,每一步都有明确的判断分支,避免"上来就重启"这种无效操作。
三、先看清链路:MySQL 的典型架构
动手之前先明确"请求经过了哪些环节",把问题定位到具体一层,排查效率会成倍提升。
四、根因分析
结合现场日志、监控与配置,逐条核对,绝大多数情况都能收敛到下面这几类原因:
- 索引列被函数包裹或发生隐式类型转换(字符串传数字)
- 没有合适索引,数据量增长后全表扫描
- 深分页 limit 100000,20 导致扫描大量行
- select * 取出无用大字段(text / blob)
- 统计信息过期,优化器选错索引
五、处置过程
处置原则:先止血、再根治。先让业务恢复,再回头解决根因,不要在故障中做长期改造。
- EXPLAIN 是第一步,不要凭感觉加索引
- 索引列上禁止使用函数与隐式转换
- 深分页改用"游标 / 上一页最大 ID"方式
- 只查需要的列,避免大字段参与排序与回表
六、关键命令与配置
下面这些命令/配置可以直接在生产上核对(执行前请确认环境与权限):
-- 慢查询定位
SELECT id, user_id, LEFT(sql_text,120) t, exec_count, avg_timer_wait/1e6 avg_ms
FROM performance_schema.events_statements_summary_by_digest
ORDER BY avg_timer_wait DESC LIMIT 10;
-- 执行计划(重点看 type / key / rows / Extra)
EXPLAIN SELECT id, amount FROM orders
WHERE user_id = 1024 AND status = 1 ORDER BY created_at DESC LIMIT 20;
-- 命中索引:KEY idx_user_status_created (user_id, status, created_at)
-- 深分页改写(避免 limit 100000,20)
SELECT id, amount FROM orders
WHERE user_id = 1024 AND id < 91827364 ORDER BY id DESC LIMIT 20;
七、复盘
故障恢复后必须做复盘,重点不是"谁的责任",而是"哪个机制缺位":
- 根因是订单表从 100 万涨到 8000 万,索引选择性下降
- 复盘发现没有慢查询日常巡检,只在故障时看
- 开发不知道"隐式类型转换会导致索引失效"这个常识点
八、预防建议
- 慢查询纳入日巡检,Top10 必须有人认领
- 数据量过千万的表必须做容量评估与归档方案
- 上线前 SQL 走评审,附带 EXPLAIN 结果
- 建立索引规范与"禁止操作"清单
九、写在最后
上面这套排查方法,是 MySQL 在生产环境中最常见的一类问题,也是大数据方向岗位面试里经常被追问的场景题。很多人搜「苏州运维」或者关心「数据库运维培训」,真正想确认的其实是:课程讲不讲真实的线上故障。我们在云计算运维工程师课程里,会把这类故障做成实战演练——从监控曲线、日志、命令输出一路推到根因,再动手恢复,而不是背命令。苏州校区面授 + 线上同步,主打苏州运维方向的实战教学,就业推荐覆盖江浙沪。如果你正在做大数据方向、或者想转行进入大数据领域,可以了解一下我们的课程(苏州运维、数据库运维培训、苏州运维哪个好),也可以直接联系我们做一次免费的职业与技术评估。