往期热门文章 1、取代 IDEACursor 3 发布VS Code 那套 IDE 过时了 2、DeepSeek 版 Claude Code 来了一个美国佬为 DeepSeek 做了一个终端 Agent 3、Prompt 已死GPT-5.5 官方发布新的提示词咒语指南 4、工作六年看到这样的代码内心五味杂陈... 5、聊聊Mybatis-Plus中的10个坑前言面试官问线上慢SQL问题导致CPU飙升如何处理这就是典型的慢SQL拖垮整个应用的案例。今天我就带大家从排查、分析到优化完整走一遍线上慢SQL导致CPU飙升的实战处理流程。希望对你会有所帮助。一、如何快速定位问题当你发现应用或数据库CPU飙升时不要慌按以下步骤快速锁定元凶。1.1 确认数据库层面的CPU消耗登录数据库服务器使用top或htop查看MySQL进程的CPU占用率。如果mysqld的CPU超过100%多核基本可以确定是数据库内部有消耗大的操作。接着进入MySQL命令行执行SHOWPROCESSLIST;重点关注Time执行时间和State状态列。如果出现大量Sending data、Copying to tmp table、Sorting result等状态的会话且执行时间很长大概率就是慢SQL。还可以开启慢查询日志如果没开的话SETGLOBAL slow_query_log 1;SETGLOBAL long_query_time 1; -- 超过1秒记录然后通过mysqldumpslow工具分析慢日志pt-query-digest /var/log/mysql/slow.log # 或使用mysqldumpslow1.2 拿到具体的SQL从SHOW PROCESSLIST中复制出问题SQL或者从慢日志中提取。例如SELECT o.id, o.amount, u.name, p.titleFROM orders oLEFTJOINusers u ON o.user_id u.idLEFTJOIN products p ON o.product_id p.idWHERE o.status PAID AND o.create_time 2026-01-01ORDERBY o.amount DESCLIMIT1000;二、为什么会慢慢SQL导致CPU飙升的根本原因是数据库需要耗费大量CPU资源去执行全表扫描、排序、创建临时表等操作。2.1 执行计划分析使用EXPLAIN查看SQL的执行计划EXPLAINSELECT ...关键列typeALL表示全表扫描最差range或ref表示用到索引。rows估算扫描行数越大越慢。ExtraUsing filesort文件排序、Using temporary临时表都很耗CPU。2.2 为什么全表扫描会飙高CPUMySQL要逐行读取数据页到内存然后逐行过滤条件。如果表很大千万级即使内存足够也要扫描大量数据CPU忙于解析和比较。排序、分组等操作需要额外内存和CPU计算。2.3 索引失效的常见场景对索引列使用函数WHERE DATE(create_time) 2026-01-01隐式类型转换WHERE user_id 123但user_id是数值类型使用!或LIKE %abc前缀模糊匹配OR 条件中有非索引列三、紧急处理措施止血在找到根本原因之前先要让系统恢复可用避免故障扩大。3.1 杀掉慢查询SHOWPROCESSLIST;-- 找到Id列和执行时间长的会话执行KILL Id;可以写脚本定时kill超过某阈值的SQL。3.2 临时限流在应用层对可疑接口进行限流例如使用Sentinel或Hystrix降低该接口的并发。3.3 重启数据库? 不推荐重启会清空buffer pool可能导致启动后更慢。除非无法连接。四、根治手段优化SQL与索引4.1 添加合适的索引针对上述例子我们分析WHERE o.status PAID AND o.create_time 2026-01-01可以考虑联合索引(status, create_time)。排序字段amount看能否加到索引中避免filesort。优化后ALTERTABLE orders ADDINDEX idx_status_time_amount (status, create_time, amount);再次EXPLAINtype变成rangerows大幅减少Extra不再有Using filesort。4.2 改写SQL避免SELECT *只取必要字段。将LEFT JOIN改为INNER JOIN如果业务允许可提前过滤掉空数据。使用子查询或临时表减少关联数据量。4.3 拆分复杂查询把一条多表JOIN拆成多条简单查询在应用层组装适合数据量不是特别大的场景。五、实战案例原始SQL订单表500万用户表200万商品表100万SELECT o.order_no, u.phone, p.name, o.amountFROM orders oLEFTJOINusers u ON o.user_id u.idLEFTJOIN products p ON o.product_id p.idWHERE o.status 1AND o.create_time BETWEEN2026-04-01AND2026-04-30ORDERBY o.amount DESCLIMIT100;问题orders表只有单列索引status导致只过滤了状态但create_time没走索引扫描了全部状态为1的历史订单。ORDER BY amount引发文件排序。优化方案创建联合索引ALTER TABLE orders ADD INDEX idx_status_time_amount(status, create_time, amount);改写SQL将LEFT JOIN改为INNER JOIN因为用户和商品一定有对应数据且不要求展示空。分页优化因为LIMIT 100已经很好。优化后执行计划typerangerows2000Extra中无Using filesort查询时间从30秒下降到0.08秒。效果数据库CPU从85%降到15%应用恢复正常。六、优缺点与适用场景优化手段优点缺点适用场景加索引效果立竿见影增加写入开销占用磁盘高频查询条件选择性好改写SQL不改变数据结构需要业务理解复杂关联、子查询拆分查询应用层组装缓解数据库压力增加网络开销和代码复杂度关联表多但单表数据不大使用缓存大幅降低DB负载一致性难保证读多写少的热点数据读写分离分散读压力主从延迟问题读远大于写七、如何预防慢SQL导致CPU飙升建立SQL审核机制上线前必须通过EXPLAINreview禁止全表扫描语句上线。开启慢查询监控配置阈值如1秒并接入告警系统。定期分析索引使用情况删除未使用的索引优化重复索引。压测大促前对核心查询进行压力测试观察CPU拐点。限流与降级在API网关或业务层配置限流防止突发流量冲击数据库。全链路压测平台提前发现潜在慢SQL。八、总结线上慢SQL导致CPU飙升本质上是一个“数据库资源被低效查询耗尽”的问题。处理的核心流程可以概括为定位慢SQL → EXPLAIN分析 → 索引优化/SQL改写 → 验证效果 → 建立事前预防机制在实际工作中80%的CPU飙升问题都可以通过加索引或简单改写SQL解决。但更重要的是我们要有敬畏之心——每一行SQL都可能成为生产事故的导火索。建立规范的开发流程和强有力的监控体系才是长久之计。往期热门文章1、为什么 Claude Code 没有一句废话扒光它的底层提示词我悟了 2、面试官尬笑你说半天就能读完一个开源项目源码不就是用 AI 吗我说是用 DeepWiki而且是 Codemap 模式 3、Claude Code、Cursor 和 Codex到底选哪个 4、GitHub 榜首竟是个 Markdown 文件还狂揽 4.5 万 Star 5、强烈建议大家使用 Linux 做开发 6、Cursor被扒底裤Claude Code套壳实锤500亿估值全靠CtrlH 7、Git 诞生 21 周年1000 命令的它是如何变臃肿的 8、一张图带你搞懂AI圈的那些“黑话” 9、开源 10 天就飙到 4 万星这个项目收集了 58 个知名网站样式。 10、面试中被嘲笑Token放在Redis里怎么应对