MySQL CPU 100% 排查指南:Java 场景下的系统化解决方案

一、现象确认与基础监控

当收到 MySQL CPU 100% 的告警时,首先需要确认现象的真实性。建议通过以下步骤进行初步验证:

  1. 多维度监控交叉验证:登录数据库服务器执行 top -H 命令,确认 mysqld 进程的 CPU 占用率确实达到阈值。同时检查系统整体负载(uptime)、磁盘 I/O 等待(iostat)和网络流量(iftop),排除因其他服务导致的资源争用。
  2. 时间维度分析:通过监控平台(如 Prometheus+Grafana)查看 CPU 突增的时间点,与业务高峰期、定时任务执行时间进行关联分析。例如某电商系统在每日 0 点执行结算任务时,因复杂 SQL 导致 CPU 峰值。
  3. 连接数监控:执行 SHOW PROCESSLIST 或查询 information_schema.processlist,重点关注 Time 列值较大的连接,这些可能是长时间运行的查询。

二、连接池与会话诊断

在 Java 应用场景中,连接池配置不当是常见诱因:

  1. 连接泄漏检测:通过 JMX 或连接池监控工具(如 HikariCP 的 Metrics)检查活跃连接数是否超过最大值。若发现连接数持续增长,需检查代码中是否存在未关闭的 Connection/Statement/ResultSet 对象。
  2. 线程阻塞分析:使用 jstack <pid> 导出线程堆栈,重点关注 WAITING 状态的线程。例如发现大量线程阻塞在 DataSource.getConnection(),表明连接池已耗尽。
  3. 连接池参数调优:根据业务特性调整以下参数:
    1. # HikariCP 示例配置
    2. maximumPoolSize=20 # 根据并发量调整
    3. connectionTimeout=30000 # 避免长时间等待
    4. idleTimeout=600000 # 合理设置空闲连接超时

三、慢查询深度优化

SQL 执行效率是 CPU 飙升的核心因素,建议按以下步骤排查:

  1. 开启慢查询日志:临时设置 long_query_time=1 并启用 slow_query_log,通过 mysqldumpslow 工具分析高频慢查询。例如发现某统计查询因缺少索引导致全表扫描。
  2. 执行计划分析:对关键 SQL 执行 EXPLAIN,重点关注以下问题:
    • 全表扫描(type=ALL)
    • 临时表使用(Using temporary)
    • 文件排序(Using filesort)
  3. 索引优化策略
    • 为 WHERE 条件、JOIN 字段、ORDER BY 字段创建复合索引
    • 避免索引失效场景(如函数操作、隐式类型转换)
    • 使用覆盖索引减少回表操作
  4. SQL 重写建议
    • OR 条件拆分为多个 UNION ALL
    • 避免 SELECT *,只查询必要字段
    • 对大表分页查询使用 WHERE id > ? LIMIT n 替代 LIMIT m,n

四、JVM 协同诊断

Java 应用与 MySQL 的交互可能引发连锁反应:

  1. GC 日志分析:若发现频繁 Full GC,检查堆内存配置(-Xms/-Xmx)是否合理。使用 jstat -gcutil <pid> 监控 GC 频率和耗时。
  2. JIT 编译影响:某些复杂查询可能触发 JIT 编译,导致 CPU 短暂飙升。可通过 -XX:+PrintCompilation 参数观察编译热点。
  3. 字节码增强工具:使用 Arthas 等工具动态跟踪 SQL 执行:
    1. # 跟踪 JDBC 方法调用
    2. trace com.mysql.jdbc.PreparedStatement executeQuery

五、架构级优化方案

对于长期存在的性能问题,需从架构层面解决:

  1. 读写分离:将读操作分流到从库,减轻主库压力。需注意主从延迟对业务的影响。
  2. 缓存策略:引入分布式缓存(如 Redis)缓存热点数据,减少数据库查询。例如将商品详情信息缓存 5 分钟。
  3. 异步化改造:对非实时要求的操作(如日志记录、统计计算)采用消息队列异步处理。
  4. 分库分表:当单表数据量超过 500 万行时,考虑按业务维度或哈希分片。

六、应急处理流程

  1. 临时降级:通过限流、熔断机制保护数据库,避免雪崩效应。
  2. 快速重启:在确认无数据丢失风险时,可重启 MySQL 服务(需评估业务影响)。
  3. 流量切换:将部分流量切换至备用数据库实例(需提前配置主从或集群)。

七、预防性措施

  1. 压力测试:使用 JMeter 或 sysbench 模拟高并发场景,提前发现性能瓶颈。
  2. 自动化巡检:编写脚本定期检查慢查询、连接数、索引使用率等指标。
  3. 变更管理:严格执行 SQL 审核流程,禁止直接在生产环境执行 DDL 操作。

总结:MySQL CPU 100% 的排查需要结合系统监控、连接池分析、SQL 优化、JVM 诊断等多维度手段。在 Java 应用场景下,特别要关注连接池配置和 JDBC 交互细节。建议建立完善的性能基线,通过自动化工具实现问题预警和快速定位,最终形成”监控-诊断-优化-验证”的闭环管理体系。