奋斗
努力

云服务器中MySQL进程常驻内存占用大,如何查看和释放?

云计算

MySQL 内存占用高是云服务器常见的问题,通常由查询缓存、连接池、缓冲池配置不当或慢查询引起。以下是系统化的排查与优化步骤:


🔍 一、查看当前 MySQL 内存占用情况

1. 查看 MySQL 进程内存使用

# 查看 mysql 进程详细内存信息
ps aux | grep mysqld
top -p $(pgrep mysqld)

# 或使用更详细的工具
htop -C -p $(pgrep mysqld)

关注 RES(常驻内存)和 VIRT(虚拟内存)列。

2. 查看 MySQL 内部内存使用情况

登录 MySQL 后执行:

-- 查看全局状态变量中的内存相关指标
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_size';
SHOW GLOBAL STATUS LIKE 'Key_buffer_size';
SHOW GLOBAL STATUS LIKE 'Query_cache_size';
SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Created_tmp_tables';
SHOW GLOBAL STATUS LIKE 'Created_tmp_disk_tables';

-- 查看当前连接数及每个连接的内存估算
SELECT * FROM information_schema.processlist;

-- 查看 InnoDB 缓冲池命中率
SELECT 
    (1 - Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests) * 100 AS hit_rate
FROM information_schema.global_status;

3. 使用性能模式(Performance Schema)深入分析

-- 启用 performance_schema
SET GLOBAL performance_schema = ON;

-- 查看最耗内存的会话
SELECT 
    PROCESSLIST_ID,
    PROCESSLIST_USER,
    PROCESSLIST_HOST,
    SUM(TIMER_WAIT/1000000000) AS total_time_sec,
    COUNT_STAR AS total_statements
FROM performance_schema.events_statements_summary_by_thread_id
GROUP BY PROCESSLIST_ID
ORDER BY total_time_sec DESC
LIMIT 10;

🧹 二、释放内存的方法

✅ 方法 1:重启 MySQL 服务(临时释放)

sudo systemctl restart mysql
# 或
sudo service mysql restart

⚠️ 注意:会导致短暂服务中断,建议在低峰期操作。

✅ 方法 2:清理查询缓存(如果开启)

-- 查看查询缓存大小
SHOW VARIABLES LIKE 'query_cache_size';
SHOW VARIABLES LIKE 'query_cache_type';

-- 清空查询缓存
FLUSH QUERY CACHE;

-- 禁用查询缓存(推荐现代 MySQL 版本)
SET GLOBAL query_cache_type = OFF;
SET GLOBAL query_cache_size = 0;

💡 MySQL 8.0+ 已移除查询缓存功能,无需处理。

✅ 方法 3:调整关键内存参数(永久优化)

编辑 /etc/my.cnf 或 /etc/mysql/my.cnf:

[mysqld]
# InnoDB 缓冲池大小(建议设为物理内存的 50%-70%)
innodb_buffer_pool_size = 1G

# 键缓冲区(仅用于 MyISAM 表,若不用可设小)
key_buffer_size = 64M

# 排序/连接缓冲区(每个连接单独分配,需控制并发)
sort_buffer_size = 2M
join_buffer_size = 2M
read_buffer_size = 1M
read_rnd_buffer_size = 1M

# 线程缓存(减少新建线程开销)
thread_cache_size = 16

# 最大连接数(根据业务调整)
max_connections = 200

# 关闭不需要的功能
query_cache_type = OFF
query_cache_size = 0

然后重启 MySQL:

sudo systemctl restart mysql

✅ 方法 4:杀死异常/空闲连接

-- 查看所有连接
SHOW FULL PROCESSLIST;

-- 杀死特定连接(替换 ID)
KILL 12345;

-- 批量杀死空闲超过 10 分钟的连接
SELECT CONCAT('KILL ', id, ';') 
FROM information_schema.processlist 
WHERE COMMAND = 'Sleep' AND TIME > 600;

✅ 方法 5:优化慢查询,减少内存消耗

-- 启用慢查询日志
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';

-- 分析慢查询
mysqlsla /var/log/mysql/slow.log

对高频慢查询添加索引或重写 SQL。


📊 三、长期监控与建议

1. 使用监控工具

  • Prometheus + Grafana + MySQL Exporter
  • Percona Monitoring and Management (PMM)
  • MySQL Enterprise Monitor

2. 定期检查项

检查项 合理范围
Innodb_buffer_pool_usage 80%~95%
Threads_connected < max_connections 的 80%
Created_tmp_disk_tables 越低越好
Handler_read_rnd_next 过高说明全表扫描多

3. 架构级优化建议

  • 使用 读写分离 分散负载
  • 引入 Redis/Memcached 缓存热点数据
  • 定期 OPTIMIZE TABLE 整理碎片
  • 升级硬件或扩容云实例

✅ 总结 Checklist

步骤 操作
1 用 ps/top 确认 MySQL 内存占用
2 用 SHOW GLOBAL STATUS 查看内部指标
3 清理查询缓存或禁用
4 调整 my.cnf 中的内存参数
5 杀死空闲/异常连接
6 优化慢查询,添加索引
7 设置监控告警,持续跟踪

如问题仍未解决,可提供以下信息以便进一步诊断:

  • MySQL 版本
  • 服务器总内存 & 配置
  • SHOW VARIABLES LIKE '%buffer%'; 输出
  • SHOW GLOBAL STATUS; 中关键字段值
未经允许不得转载:云服务器 » 云服务器中MySQL进程常驻内存占用大,如何查看和释放?