【紧急救援】MySQL CPU 100%!一套组合拳教你快速定位并解决!

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
简介: 凌晨三点MySQL CPU飙至100%,业务瘫痪!本文亲历30分钟应急排障全过程:从紧急止血、定位慢查询、分析锁争用,到优化SQL与索引,最终恢复服务。总结一套可复用的排查路径与预防方案,助你告别深夜救火。

凌晨三点,报警短信炸醒:MySQL CPU 100%!业务全挂!别慌,看我如何30分钟搞定这个"午夜惊魂"!

事故现场:CPU爆表的惨状

监控告警:

  • CPU使用率:100%
  • 连接数:爆满
  • QPS:断崖式下跌
  • 业务接口:全部超时

内心OS: 这要是搞不定,明天就可以卷铺盖走人了!


第0步:别慌,深呼吸 先问自己

  • 是突然飙升还是缓慢上涨?
  • 业务高峰时段还是平时?
  • 最近有没有上线新功能

就像医生看病先问诊,咱也得先了解病情。


第一步:紧急止血(5分钟搞定)

CPU 100%的时候,别想着一步到位解决问题,先让服务活过来最重要。

1.1 快速连接MySQL(30秒)

-- 紧急登录(跳过权限验证)
mysql -h 127.0.0.1 -u root -p --skip-secure-auth

-- 如果连接不上,强制重启(最后手段)
sudo systemctl restart mysql

1.2 查看当前状态

-- 查看当前连接和进程
SHOW PROCESSLIST;

-- 查看全局状态
SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Queries';

关键观察点:

  • 是否有大量Sleep连接?
  • 是否有长时间运行的查询?
  • 是否有锁等待?

1.3 紧急止血操作

-- 杀死长时间运行的查询
SELECT * FROM information_schema.PROCESSLIST 
WHERE COMMAND != 'Sleep' 
AND TIME > 60 
ORDER BY TIME DESC;

-- 逐个杀死问题进程
KILL 12345;
KILL 12346;

-- 调整关键参数(临时生效)
SET GLOBAL innodb_buffer_pool_size = 2147483648; -- 2GB
SET GLOBAL tmp_table_size = 268435456;          -- 256MB
SET GLOBAL max_heap_table_size = 268435456;     -- 256MB
SET GLOBAL thread_cache_size = 16;

-- 清理缓存和临时表
FLUSH TABLES;
FLUSH QUERY CACHE;
RESET QUERY CACHE;

第二步:问题定位(10分钟深度排查)

2.1 实时监控关键指标

-- 查看当前活跃的慢查询
SELECT * FROM information_schema.PROCESSLIST 
WHERE COMMAND != 'Sleep' 
AND INFO IS NOT NULL 
ORDER BY TIME DESC 
LIMIT 10;

-- 查看锁等待情况
SELECT * FROM information_schema.INNODB_LOCKS;
SELECT * FROM information_schema.INNODB_LOCK_WAITS;

2.2 开启慢查询日志分析

-- 临时开启慢查询日志(不用重启)
SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 1;
SET GLOBAL slow_query_log_file = '/tmp/slow.log';

-- 查看当前慢查询配置
SHOW VARIABLES LIKE 'slow_query%';
SHOW VARIABLES LIKE 'long_query_time';

2.3 使用性能分析工具

# 使用mysqldumpslow分析慢日志
mysqldumpslow -s t -t 10 /var/lib/mysql/slow.log

# 使用pt-query-digest(更强大)
pt-query-digest /var/lib/mysql/slow.log

# 实时查看服务器状态
mysqladmin -u root -p ext -i 1

第三步:深度排查方向

方向1:SQL查询问题

-- 查看执行次数最多的SQL
SELECT DIGEST_TEXT, COUNT_STAR, AVG_TIMER_WAIT
FROM performance_schema.events_statements_summary_by_digest
ORDER BY COUNT_STAR DESC
LIMIT 10;

-- 查看响应时间最长的SQL
SELECT DIGEST_TEXT, AVG_TIMER_WAIT, MAX_TIMER_WAIT
FROM performance_schema.events_statements_summary_by_digest
ORDER BY AVG_TIMER_WAIT DESC
LIMIT 10;


-- 分析慢查询日志 
mysqldumpslow -s t /var/lib/mysql/slow.log pt-query-digest /var/lib/mysql/slow.log 
-- 实时查看慢查询 
SELECT * FROM mysql.slow_log ORDER BY start_time DESC LIMIT 10;

方向2:索引问题排查

-- 查看没有使用索引的查询
SELECT * FROM sys.schema_unused_indexes;

-- 查看缺失索引的情况
SELECT * FROM sys.schema_index_statistics WHERE INDEX_NAME IS NOT NULL;
SELECT * FROM sys.statements_with_sorting;

-- 查看表扫描情况
SELECT * FROM sys.schema_tables_with_full_table_scans limit 10;

方向3:锁竞争分析

-- 查看当前锁信息
SELECT * FROM performance_schema.data_locks;
SELECT * FROM performance_schema.data_lock_waits;

-- 查看等待锁的线程
SELECT * FROM sys.innodb_lock_waits;

-- 查看表锁情况
SHOW STATUS LIKE 'Table_locks_%';

方向4:连接数暴增

-- 查看连接来源
SELECT * FROM information_schema.PROCESSLIST 
WHERE HOST NOT LIKE '127.0.0.1%' 
AND HOST NOT LIKE 'localhost%';

-- 查看最大连接数
SHOW VARIABLES LIKE 'max_connections';
SHOW STATUS LIKE 'Threads_connected';

-- 杀掉异常连接(谨慎使用!)
SELECT CONCAT('KILL ', id, ';') 
FROM information_schema.PROCESSLIST 
WHERE USER = 'bad_user' 
OR TIME > 300;

方向5:配置参数问题

-- 🎯 检查关键配置参数
SHOW VARIABLES WHERE Variable_name IN (
    'innodb_buffer_pool_size',
    'query_cache_size',
    'tmp_table_size',
    'max_heap_table_size',
    'max_connections'
);

第四步:常见问题及解决方案

问题1:慢查询导致的CPU飙升

症状: 大量SQL执行时间超过1秒

问题SQL:

-- ❌ 慢查询示例
SELECT * FROM orders 
WHERE DATE(create_time) = '2024-01-01'
AND status IN (1,2,3,4,5,6,7,8,9,10)
ORDER BY id DESC 
LIMIT 1000;

解决方案:

-- 使用EXPLAIN分析问题SQL
EXPLAIN SELECT * FROM orders 
WHERE DATE(create_time) = '2024-01-01'
AND status IN (1,2,3,4,5,6,7,8,9,10)
ORDER BY id DESC 
LIMIT 1000;

-- 优化方案:添加索引或者改写SQL
-- 索引优化策略
-- 删除冗余索引
SELECT * FROM sys.schema_redundant_indexes;

-- 添加缺失索引
SELECT * FROM sys.schema_index_statistics 
WHERE table_schema = 'your_database';

-- 复合索引设计原则
-- 1. 等值查询字段在前
-- 2. 范围查询字段在后  
-- 3. 排序字段考虑在内

优化方案:

-- ✅ 优化后
SELECT * FROM orders 
WHERE create_time >= '2024-01-01 00:00:00' 
AND create_time < '2024-01-02 00:00:00'
AND status BETWEEN 1 AND 10
ORDER BY id DESC 
LIMIT 1000;

-- 添加索引
ALTER TABLE orders 
ADD INDEX idx_create_time_status (create_time, status);

问题2:全表扫描

症状: 没有使用索引,扫描大量数据

解决方案:

-- 查找需要添加索引的表
SELECT * FROM sys.schema_tables_with_full_table_scans;

-- 为常用查询字段添加索引
ALTER TABLE orders ADD INDEX idx_user_status(user_id, status);
ALTER TABLE products ADD INDEX idx_category_price(category_id, price);

问题3:锁等待和死锁

症状: 大量进程处于"Waiting for table metadata lock"

解决方案:

-- 查看当前锁信息
SELECT * FROM performance_schema.data_locks;
SELECT * FROM performance_schema.data_lock_waits;

-- 优化事务,减少锁持有时间
-- 将大事务拆分为小事务
START TRANSACTION;
-- 分批处理数据
COMMIT;

问题4:配置不合理

症状: 缓冲区设置过小,频繁磁盘IO

解决方案:

-- 优化InnoDB缓冲池(建议设置为物理内存的70-80%)
SET GLOBAL innodb_buffer_pool_size = 2147483648; -- 2GB

-- 调整连接数
SET GLOBAL max_connections = 500;

-- 调整临时表大小
SET GLOBAL tmp_table_size = 67108864; -- 64MB
SET GLOBAL max_heap_table_size = 67108864;

第五步:实战排查脚本

监控预警:建立防护体系

监控指标清单

监控项 预警阈值 检查频率
CPU使用率 >80% 1分钟
连接数 >max_connections的80% 1分钟
慢查询数量 >10个/分钟 5分钟
锁等待时间 >30秒 1分钟
缓冲池命中率 <95% 5分钟

5.1 自动化脚本示例

#!/bin/bash
#  MySQL健康检查脚本

CPU_THRESHOLD=80
CONN_THRESHOLD=100

check_mysql_health() {
   
    # 检查CPU
    CPU_USAGE=$(top -bn1 | grep "mysql" | head -1 | awk '{print \$9}')
    if (( $(echo "$CPU_USAGE > $CPU_THRESHOLD" | bc -l) )); then
        echo "🚨 CPU使用率过高: $CPU_USAGE%"
        # 发送告警...
    fi

    # 检查连接数
    CONN_COUNT=$(mysql -e "SHOW STATUS LIKE 'Threads_connected'" | grep Threads_connected | awk '{print \$2}')
    if [ $CONN_COUNT -gt $CONN_THRESHOLD ]; then
        echo "🚨 连接数过多: $CONN_COUNT"
        # 发送告警...
    fi
}

5.2 一键排查脚本

#!/bin/bash
# MySQL CPU 100% 一键排查脚本

echo " 开始MySQL性能问题排查..."

# 检查连接数
mysql -u root -p -e "SHOW STATUS LIKE 'Threads_connected';"

# 检查慢查询
mysql -u root -p -e "SHOW VARIABLES LIKE 'slow_query_log';"

# 检查当前进程
mysql -u root -p -e "SHOW PROCESSLIST;"

# 检查锁等待
mysql -u root -p -e "SELECT * FROM information_schema.INNODB_LOCK_WAITS;"

echo " 排查完成!"

5.3 实时监控脚本

#!/bin/bash
# 实时监控MySQL状态

while true; do
    clear
    echo "$(date) - MySQL状态监控"
    echo "========================"

    # 查看连接数
    mysql -u root -p -e "SHOW STATUS LIKE 'Threads_connected';" 2>/dev/null

    # 查看当前查询
    mysql -u root -p -e "SHOW PROCESSLIST;" 2>/dev/null | head -20

    sleep 2
done

预防措施:避免再次发生

开发规范

--  必须使用EXPLAIN分析查询
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';

-- 禁止SELECT *,明确字段
SELECT id, name, email FROM users;

-- 大数据量使用分页
SELECT * FROM orders LIMIT 100 OFFSET 0;

-- 事务要短小精悍
START TRANSACTION;
-- 快速操作...
COMMIT;

运维规范

-- ✅ 定期分析表
ANALYZE TABLE important_table;

-- ✅ 定期优化表
OPTIMIZE TABLE fragmented_table;

-- ✅ 监控索引使用情况
SELECT * FROM sys.schema_index_statistics;

-- ✅ 定期清理历史数据
DELETE FROM log_table WHERE create_time < DATE_SUB(NOW(), INTERVAL 30 DAY);

血泪教训

  • 不要相信"这个查询很快" - 在小数据量下跑得快,到生产环境可能就跪了
  • 索引不是越多越好 - 就像吃药,要对症下药
  • 监控比救火重要 - 等CPU 100%再处理,黄花菜都凉了
  • 测试数据要真实 - 用几十条数据测试,上线后面对几百万数据直接傻眼

性能调优参数参考

# my.cnf 关键配置
[mysqld]
# 内存相关
innodb_buffer_pool_size = 4G
innodb_log_file_size = 1G
tmp_table_size = 256M
max_heap_table_size = 256M

# 连接相关  
max_connections = 200
thread_cache_size = 16

# 查询相关
query_cache_type = 1
query_cache_size = 128M
long_query_time = 2
slow_query_log = 1

# InnoDB相关
innodb_flush_log_at_trx_commit = 2
innodb_lock_wait_timeout = 50

总结

MySQL CPU 100%排查黄金法则:

  1. 立即行动SHOW PROCESSLIST 快速定位
  2. 精准打击 → 分析慢查询、索引、锁竞争
  3. 紧急救援 → 终止问题查询、调整参数
  4. 根治问题 → SQL优化、索引重构、架构升级
  5. 建立防护 → 监控预警、开发规范、定期维护

记住这个排查路径:

紧急响应 → 深度排查 → 立即解决 → 根治问题 → 预防再发

从此告别:

  • 半夜被报警吵醒
  • 手忙脚乱救火
  • 业务长时间中断
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
4月前
|
缓存 关系型数据库 MySQL
降低MySQL高CPU使用率的优化策略。
通过上述方法不断地迭代改进,在实际操作中需要根据具体场景做出相对合理判断。每一步改进都需谨慎评估其变动可能导致其他方面问题,在做任何变动前建议先在测试环境验证其效果后再部署到生产环境中去。
206 6
|
11月前
|
存储 设计模式 监控
快速定位并优化CPU 与 JVM 内存性能瓶颈
本文介绍了 Java 应用常见的 CPU & JVM 内存热点原因及优化思路。
1044 166
|
8月前
|
监控 C#
【Function App】如果一个拥有多个Function App的Plan遇见了High CPU问题? 如何方便定位是哪一个Function App引发的呢?
在Azure Function App测试中,若多个Function App共用同一App Service Plan资源,当出现High CPU问题时,由于Function App公开指标无法直接观测CPU状态,可通过启用Application Insights解决。其Live Metrics功能可过滤并查看每个Function App的CPU使用情况。具体步骤为:将所有Function App连接至同一Application Insights资源,进入Live Metrics页面按Role筛选监控数据。附有三段C#代码示例,分别展示占用CPU、Memory及普通功能的实现方法。
219 36
线程CPU异常定位分析
【10月更文挑战第3天】 开发过程中会出现一些CPU异常升高的问题,想要定位到具体的位置就需要一系列的分析,记录一些分析手段。
290 0
|
9月前
|
存储 设计模式 监控
如何快速定位并优化CPU 与 JVM 内存性能瓶颈?
如何快速定位并优化CPU 与 JVM 内存性能瓶颈?
252 0
如何快速定位并优化CPU 与 JVM 内存性能瓶颈?
|
SQL 监控 关系型数据库
MySQL优化: CPU高 处理脚本 pt-kill脚本
MySQL优化: CPU高 处理脚本 pt-kill脚本
|
10月前
|
监控 关系型数据库 MySQL
如何解决 MySQL 数据库服务器 CPU 飙升的情况
大家好,我是 V 哥。当 MySQL 数据库服务器 CPU 飙升时,如何快速定位和解决问题至关重要。本文整理了一套实用的排查和优化套路,包括使用系统监控工具、分析慢查询日志、优化 SQL 查询、调整 MySQL 配置参数、优化数据库架构及检查硬件资源等步骤。通过一个电商业务系统的案例,详细展示了从问题发现到解决的全过程,帮助你有效降低 CPU 使用率,提升系统性能。关注 V 哥,掌握更多技术干货。
1316 0
|
小程序 JavaScript Java
【Java】服务CPU占用率100%,教你用jstack排查定位
本文详细讲解如何使用jstack排查定位CPU高占用问题。首先介绍jstack的基本概念:它是诊断Java应用程序线程问题的工具,能生成线程堆栈快照,帮助找出程序中的瓶颈。接着,文章通过具体步骤演示如何使用`top`命令找到高CPU占用的Java进程及线程,再结合`jstack`命令获取堆栈信息并进行分析,最终定位问题代码。
1584 2
【Java】服务CPU占用率100%,教你用jstack排查定位
|
Java
Java面试题之cpu占用率100%,进行定位和解决
这篇文章介绍了如何定位和解决Java服务中CPU占用率过高的问题,包括使用top命令找到高CPU占用的进程和线程,以及使用jstack工具获取堆栈信息来确定问题代码位置的步骤。
927 0
Java面试题之cpu占用率100%,进行定位和解决
|
监控 关系型数据库 MySQL
在Linux中,mysql的innodb如何定位锁问题?
在Linux中,mysql的innodb如何定位锁问题?

推荐镜像

更多