← 每日面试题 学习看板

数据库CPU被打满排查过程

面试题/01实践场景题/问题排查/数据库CPU被打满排查过程.md

面试记录 2026-10-22

题目:数据库 CPU 被打满排查过程

难度:medium

标签:practice/debug, mysql/cpu, mysql/deadlock, difficulty/medium

评分:⭐⭐⭐☆☆(3/5)

我的回答

如果出现mysql的cpu暴涨,先去检查数据库的连接池情况,是否链接都占满了,如果是链接都占满了,检查当前在执行的sql都有什么,确认具体是因为什么原因导致的占满;

如果是有慢SQL,那么是有慢SQL持续拿着链接,导致其他sql无法正常执行,如果不是慢SQL,那是否当前有大量更新同数据,导致行锁等待,锁冲突,导致无法正常执行;

另外检查是否出现死锁,导致无法正常执行;检查服务器是否有大批数据写入或者数据同步之类的操作,查看当前活跃线程,看具体执行内容,以及执行的设备,看是有手动执行内容,还是有什么计划任务导致大批数据获取,一步步定位到问题点,如果是有人手动或者计划任务,确认下是否可停止,不要影响线上服务;然后做出规范,收回外部权限,并且对计划任务进行拆解,把大事务拆解成小事务,分段执行,并且把执行时间放在业务低谷期

点评

优点:有完整的业务视角——连接占用 → 活跃 SQL → 加锁等待 → 批量任务/同步 → 人为操作,最后落到了权限回收、大事务拆小、错峰执行这些治理动作,这是很多人答不到的。也注意到了"是手动还是计划任务"这个区分。

不足:① 锁等待和死锁通常让 CPU 降下来而不是打满,把锁冲突当 CPU 高的原因是方向性偏差——锁等待表现为连接堆积、响应变慢,Threads_running 高但 CPU 未必高;② 缺少具体的观测命令:SHOW PROCESSLIST、performance_schema.events_statements_summary_by_digest、sys.statement_analysis、SHOW ENGINE INNODB STATUS、慢日志 + pt-query-digest;③ 没有先确认"CPU 是不是 mysqld 吃的"——要先 top 看进程、pidstat 看是否 %sys 高,排除备份、同步工具(mysqldump、xtrabackup)和其他进程;④ 没提执行计划突变、索引缺失、Buffer Pool 命中率下降这些更常见的真因。

补充:CPU 被打满的高频真因排序大致是:慢查询/全表扫描(缺索引、函数导致索引失效、隐式类型转换)→ 执行计划突变(统计信息过期、force index 失效)→ 高并发小查询把 QPS 顶爆 → 排序/临时表/大结果集 → 备份或数据同步 → 锁等待(这类 CPU 反而不高,但连接会堆)。定位时先看 Threads_running 与 QPS 的对应关系:QPS 不高但线程多,多半在等锁或等 IO。

完整讲解

第一部分:知识重点剖析

核心考点定位:考察能不能用"从外到内"的顺序把 MySQL CPU 问题收敛到一条 SQL,并且能区分"算得多"(CPU 真高)与"等得多"(CPU 不高)两种假象。

知识点拆解:

  1. 先确认是谁在吃 CPU:OS 层 top 看 mysqld 占用,pidstat -p <pid> 1 区分 %usr 与 %sys。%sys 高常见于大量系统调用、上下文切换;再看是否有备份、数据同步、监控采集在抢 CPU。
  2. 再看负载形态:SHOW GLOBAL STATUS LIKE 'Threads_running'、Questions、Com_select 算 QPS。QPS 高且 CPU 高 = 短查询海量并发,通常缺索引或热点行;QPS 低但 CPU 高 = 少数重量级 SQL(大排序、大聚合、全表扫描);QPS 低、线程多、CPU 不高 = 锁等待或 IO 等待。
  3. 定位具体 SQL:SHOW FULL PROCESSLIST 看正在执行的语句与状态(Sending data、Copying to tmp table、Waiting for lock);performance_schema.events_statements_summary_by_digest 按总耗时排序找 TOP SQL;sys.statement_analysis 直接给格式化结果;慢日志配合 pt-query-digest 做聚合。
  4. 确认执行计划:对 TOP SQL 跑 EXPLAIN / EXPLAIN FORMAT=JSON,看 type 是否 ALL、rows 是否爆炸、Extra 是否有 Using filesort / Using temporary;对比历史计划判断是否突变(统计信息、数据量分布变化)。
  5. 锁与死锁的判别:SHOW ENGINE INNODB STATUS 看 LATEST DETECTED DEADLOCK 与 TRANSACTIONS;performance_schema.data_locks / data_lock_waits(8.0)看阻塞链。注意:死锁会被自动回滚,持续锁等待才是连接堆积的主因。
  6. 治理动作:优先 KILL 掉最重的单条 SQL 止血;对批量任务拆批、限流、错峰;补索引并验证;回收高危账号的写权限;加慢查询与 Threads_running 告警。
按「底层原理 → 设计权衡 → 工程实践」递进排列。

第二部分:考察方向与延伸递进

考察方向:

延伸递进面试题:

  1. CPU 打满但 SHOW PROCESSLIST 里 SQL 都很快,可能是什么原因?
  1. 锁等待会让 CPU 变高吗?
  1. 怎么判断是索引问题还是数据量问题?

第三部分:面试者参考回答(三步法口语化,300-400 字)

【一句话结论】

面试官您好,我会先确认 CPU 到底是不是 mysqld 吃的,再用"QPS 与线程数的组合"判断是算得多还是等得多,最后落到具体 SQL。

【三点展开】

第一,先分层。OS 上 top 和 pidstat 确认是 mysqld 而不是备份或同步工具在抢 CPU,再看 %usr 和 %sys 的构成。然后拿 Threads_running 和 QPS 对照:QPS 高、CPU 高,多半是海量短查询,通常缺索引;QPS 低、CPU 高,是少数重量级 SQL 在做大排序或全表扫描;线程多但 CPU 不高,那是在等锁或等 IO,方向完全不同。

第二,定位 SQL。SHOW FULL PROCESSLIST 看正在跑什么、卡在什么状态,performance_schema 的 digest 表按总耗时排 TOP,慢日志用 pt-query-digest 聚合,然后对 TOP SQL 做 EXPLAIN,看 type 是不是 ALL、rows 有没有爆炸、有没有 filesort 和临时表。

第三,止血和治理。先 kill 掉最重的单条 SQL,必要时对批量任务限流;然后补索引、把大事务拆小、错峰执行,回收高危账号权限,最后补上慢查询和 Threads_running 的告警。

【一句边界】

当然,如果是锁等待或死锁导致的连接堆积,CPU 往往不高,这时候盯着 CPU 看会误判,要直接查 InnoDB 的锁等待链。