MySQL慢查询暴增,排查别乱了节奏 📅 2026/6/23 14:24:44 线上系统运行中MySQL慢查询突然开始增加接口响应时间跟着拉长应用连接池接近上限数据库CPU也抬了起来。群里很快会出现各种判断是不是数据库配置不够是不是要扩容要不要先重启应用要不要把连接数调大这些动作有的能缓解压力有的可能会把问题放大。慢查询暴增背后可能是一条SQL访问路径变差也可能是索引没有命中、长事务堵住后续请求、缓存失效导致流量直打数据库还可能和刚上线的代码、定时任务、活动流量有关。排查这类问题关键在于顺序。顺序对了十几分钟能缩小范围顺序乱了很容易盯着一堆指标来回切换最后只能靠经验猜。先看影响范围慢查询出现后第一步应该确认业务影响而不是马上调整数据库。先看哪些接口变慢是全部业务都受影响还是集中在订单列表、报表查询、库存扣减、用户搜索这几个接口上。再看慢的是读请求还是写请求压力在主库还是从库是否伴随主从延迟、连接池等待、接口超时。如果只是报表查询变慢优先怀疑大范围扫描、排序、分组或分页。如果下单、支付、库存等写入链路变慢要重点关注锁等待、长事务和主库写压力。如果用户侧接口正常后台任务变慢可以先限制任务执行速度避免后台任务继续抢数据库资源。这个阶段不要急着把连接数调大。连接数变多不代表数据库处理能力变强。如果SQL执行很慢更多连接只会排队更久还可能让CPU、IO和锁竞争进一步升高。拉一条时间线故障现场看到的指标往往已经是连锁反应之后的状态。慢查询、CPU、连接数、接口超时可能都在升高但它们不一定同时开始。排查时建议先把时间线拼出来慢查询从几点开始增加哪个接口先变慢应用连接池什么时候告警数据库CPU和IO什么时候升高最近一次发布或配置调整在什么时候定时任务是否刚好启动。比如慢查询在10:03开始明显增加10:05接口耗时升高10:07连接池告警10:10 MQ消费延迟。这条线说明数据库访问很可能是早期异常点。如果应用线程先堆积随后数据库慢查询增加就要回到应用层看是否有线程池耗尽、下游接口超时、连接释放慢等问题。时间线可以从监控曲线、慢日志、应用日志、发布平台、任务调度平台里拼出来。不需要做得很复杂先把关键节点按分钟排出来排查方向会清楚很多。找最可疑的SQL慢查询日志里可能有很多SQL。故障现场没时间逐条分析先挑对系统影响最大的SQL。可以优先看两类一类是单次执行时间变长的SQL另一类是调用次数突然变多的SQL。前者可能是执行计划、索引、锁等待出了问题后者单次可能不算夸张但高频执行后会把数据库压住。慢日志里有几个字段很值得看。query_time 表示执行耗时rows_examined 表示扫描行数rows_sent 表示返回行数。如果扫描几十万行最后只返回几十行这条SQL就很可疑。它可能没走到合适索引也可能条件写法让索引用不上。还有一类SQL平时不显眼业务量一上来就暴露问题。比如用户列表带多个筛选条件测试环境只有几万条数据生产有几千万条数据再加一个排序字段或模糊搜索执行时间可能从几十毫秒变成几秒。找SQL时不要只看最慢的一条也要看总耗时。某条SQL单次500毫秒每分钟执行几万次对数据库的压力可能比一条偶发10秒的SQL更大。执行计划要结合数据量看找到可疑SQL后需要看执行计划。这里最容易出现误判看到执行计划里显示用了索引就觉得问题不在SQL。用了索引不代表用得合适。联合索引字段顺序不匹配、过滤条件选择性差、范围查询放在前面、排序字段不在索引里都可能让数据库扫描大量数据。还有隐式类型转换比如字段是字符串查询条件传了数字也可能影响索引使用。排查时重点看访问类型、使用的索引、预估扫描行数、是否出现临时表和文件排序。order by、group by、大分页、复杂关联都容易把执行成本抬高。举个常见场景一个订单查询SQL原本按用户ID和状态过滤后来新增了按创建时间倒序分页。开发环境数据少看不出问题生产环境同一个用户下订单量大分页越往后越慢。这个问题不一定靠加机器解决更可能需要调整索引、限制分页深度或者改成基于游标的查询方式。执行计划只是线索还要结合表数据量、字段分布、业务调用频率一起判断。锁等待和长事务经常被漏掉慢查询暴增时不要只盯SELECT。有时SQL本身并不复杂但一直在等锁。例如某个批量更新任务开启事务后迟迟不提交占住一批记录锁。后续更新请求排队等待应用侧表现为接口慢、连接池耗尽数据库里则看到大量会话处于等待状态。还有些后台任务会在业务高峰期跑批量删除、批量更新或者执行DDL操作。单独看任务没问题放到高峰期就会影响在线交易。排查时可以看当前事务、锁等待、活跃会话、是否存在长时间未提交事务。若确认是某个任务导致阻塞处理前要和业务确认影响。订单、支付、账务、库存这类场景尤其要谨慎不能只为了恢复指标就随意终止会话。对锁问题来说止血动作通常不是优化SQL而是先处理阻塞源暂停任务、回滚异常发布或者临时切走部分流量。缓存失效会把MySQL拖下水很多MySQL慢查询暴增根源在缓存层。一个热点接口平时大部分请求走Redis数据库压力很低。某次发布后缓存key规则改了或者大量热点key同时过期请求绕过缓存直接查库MySQL流量会突然上升。慢查询开始增加应用连接池也被拖住。这类问题如果只盯MySQL排查会绕远。要同时看Redis命中率、热点key变化、缓存过期策略、是否有缓存穿透请求、应用是否走了降级逻辑。处理上也不能只改数据库。更快的方式可能是恢复缓存、预热热点数据、临时限流或者对非核心查询做降级。等流量恢复正常后再补缓存保护策略比如互斥加载、过期时间打散、热点key监控等。近期变更要重点排查线上“突然”出问题大多能在变更里找到线索。代码发布、SQL改动、索引调整、报表上线、任务调度变更、缓存策略调整、活动流量进入都可能触发慢查询暴增。有个典型案例某业务上线了一个新的筛选条件接口逻辑只是多拼了一个字段。测试环境查询很快发布后生产慢查询快速上升。最后发现新条件改变了原来的索引匹配方式数据库扫描行数从几千变成几十万。这个问题从代码看改动很小从数据库看影响很大。所以排查时要把发布记录和慢查询时间点对齐。如果时间高度重合优先看这次变更涉及的SQL、接口和缓存逻辑。能回滚的先评估回滚能关闭开关的先关闭开关。故障期间不要坚持在线上边猜边改复杂SQL。处理顺序先止血再治理慢查询暴增时现场目标是让业务恢复稳定。长期优化可以放在故障后做现场先控制影响面。常见止血动作包括限制问题接口流量暂停报表和批处理任务回滚最近发布关闭新增查询入口恢复缓存处理异常锁等待临时把部分读请求切到只读实例。加索引要看时机。大表在线加索引可能带来额外压力尤其在高峰期。如果没有把握宁愿先降级或限流等业务低峰再处理。扩容也要分场景如果是容量长期不足扩容有意义如果是一条SQL高频扫大表扩容只能短时间缓一下。故障恢复后再做长期治理。核心SQL上线前做执行计划检查大表查询加规范慢SQL按业务模块归属定时任务增加限速和告警报表库和交易库尽量隔离缓存热点数据加保护数据库连接池设置合理上限。这些工作不复杂但需要持续做。慢查询问题很少一次性清干净业务变化后还会冒出来。企业现场需要日常巡检在企业环境里MySQL慢查询暴增往往不是孤立事件。很多系统长期缺少慢SQL治理平时只在故障后查几条日志业务恢复后就停下来了。等数据量继续增长或者新功能上线类似问题还会再出现。据我了解江苏立维运维服务在数据库运维、云运维、驻场运维和7×24保障中处理过不少这类场景。他们通常不会只看数据库CPU或慢日志而是把应用接口、连接池、Redis命中率、任务调度、发布记录放在一起分析先判断压力从哪里传来再决定止血动作。这类服务更适合放在日常。比如定期做MySQL健康巡检梳理慢SQL排行检查索引缺失和冗余评估备份恢复可用性完善告警阈值和应急预案。对于内部DBA和运维人手有限、系统又比较多的企业外部团队参与巡检和应急支持可以减少临时救火的压力。MySQL慢查询突然暴增排查时别被告警带着跑。先确认影响范围再拉时间线然后看可疑SQL、执行计划、锁等待、缓存和近期变更。线上处理要先稳住业务再做SQL、索引、架构和流程层面的治理。慢查询表面发生在数据库背后常常连着代码习惯、业务流量、缓存策略和运维流程。排查顺序清楚现场就不会乱。平时把巡检、告警和SQL治理做好遇到问题时才有判断依据。