2 核云服务器配置较低,跑 MySQL 时 CPU 占用过高通常是因为查询未优化、索引缺失、连接数过多或参数配置不合理。以下是系统化的排查与解决方案:
🔍 一、快速诊断(先定位问题)
-
查看当前负载与进程
top -c | grep mysql # 或使用 htop 直观查看 -
检查 MySQL 慢查询日志(关键!)
SHOW VARIABLES LIKE 'slow_query_log'; SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 1; -- 记录执行超过 1 秒的 SQL查看日志文件(默认
/var/log/mysql/slow.log),找出高频/耗时 SQL。 -
分析线程状态
SHOW PROCESSLIST; -- 重点关注 State 为 "Sending data", "Sorting result", "Copying to tmp table" 等长时间阻塞的线程 -
检查连接数
SHOW STATUS LIKE 'Threads_connected'; SHOW VARIABLES LIKE 'max_connections';
🛠️ 二、针对性优化措施
✅ 1. 优化 SQL 与添加索引(最有效)
- 对
WHERE,ORDER BY,JOIN ON字段建立合适索引。 - 避免
SELECT *,只查必要字段。 - 避免在索引列上做函数运算(如
WHERE YEAR(create_time) = 2024→ 改为范围查询)。 - 使用
EXPLAIN分析执行计划:EXPLAIN SELECT ...; -- 关注 type(是否为 ALL/INDEX)、key(是否用索引)、rows(扫描行数)
✅ 2. 调整 MySQL 配置(适配 2 核环境)
编辑 /etc/my.cnf 或 /etc/mysql/my.cnf,重点调整:
[mysqld]
# 内存分配(2 核建议总内存 50%~70% 给 MySQL)
innodb_buffer_pool_size = 512M # 若总内存 2G;若 4G 可设 1.5G
query_cache_size = 0 # MySQL 8.0+ 已移除 query cache,勿启用
# 连接控制
max_connections = 100 # 根据实际并发调整,避免过高
thread_cache_size = 20
# 减少临时表开销
tmp_table_size = 64M
max_heap_table_size = 64M
# 日志优化(生产环境谨慎开启)
log_queries_not_using_indexes = ON
long_query_time = 1
slow_query_log_file = /var/log/mysql/slow.log
💡 重启 MySQL 生效:
systemctl restart mysqld
✅ 3. 限制高消耗操作
- 禁止用户执行
ALTER TABLE,OPTIMIZE TABLE等高 IO/CPU 操作(通过权限控制)。 - 设置会话级超时:
SET SESSION wait_timeout = 300; SET SESSION interactive_timeout = 300;
✅ 4. 升级或切换存储引擎
- 确保大表使用 InnoDB(默认),避免 MyISAM(锁粒度粗,CPU 易飙升)。
- 对只读报表场景,可考虑 Partitioning 分区表提升效率。
✅ 5. 应用层优化
- 引入缓存(Redis/Memcached)减少重复查询。
- 批量操作代替循环单条查询(如
INSERT INTO t VALUES (...), (...), (...))。 - 读写分离:主库写,从库读(即使单机也可模拟分库逻辑)。
📊 三、监控与持续改进
- 安装 Prometheus + Grafana + mysqld_exporter 实时监控 QPS、TPS、缓冲池命中率、慢查询趋势。
- 定期运行
mysqltuner.pl脚本获取自动调优建议(需安装:apt install perl-tuner或源码编译)。
⚠️ 注意事项
- 不要盲目调大
innodb_buffer_pool_size(超出物理内存会导致 swap,反而更慢)。 - 若业务本身复杂度高(如大量 JOIN、子查询),2 核可能确实不足,考虑:
- 垂直扩容(升级到 4 核)
- 水平拆分(Sharding)
- 将计算密集型任务迁移到独立服务(如 ETL 走 Spark/Flink)
如果提供具体场景(如:是 Web 应用?数据量多大?典型慢 SQL 示例?),我可以给出更精准的优化方案。
PHPWP博客