云服务器装个MySQL内存满了?

云计算

云服务器 MySQL 内存爆满通常是因为默认配置(尤其是 innodb_buffer_pool_size)占用了过多物理内存,导致服务器被 OOM Killer 杀掉进程或系统卡死。

解决思路是限制 MySQL 的内存占用,确保留出足够内存给操作系统和其他应用。以下是具体的排查和调优步骤:

1. 紧急处理(防止服务中断)

如果当前 MySQL 已经无法连接或 CPU/内存飙升:

  • 重启 MySQL 服务:临时释放内存,但问题会复发。
    sudo systemctl restart mysql
    # 或者
    sudo service mysqld restart
  • 检查是否被杀:查看系统日志确认是否触发了 OOM。
    dmesg | grep -i "out of memory"
    # 或
    journalctl -xe | grep -i "killed process"

2. 核心配置调整(永久解决方案)

修改 MySQL 配置文件(通常在 /etc/my.cnf/etc/mysql/my.cnf),重点调整以下参数。注意:不要设置得过大,建议保留 20%-30% 的物理内存给操作系统和其他进程。

A. 调整 InnoDB 缓冲池大小 (最关键)

这是占用内存的大头。对于独享型云服务器,通常设置为物理内存的 50%~75%;如果是多租户共享环境,建议更低(如 25%)。

[mysqld]
# 假设服务器有 4GB 内存,建议设为 1G ~ 2G (单位:M)
innodb_buffer_pool_size = 1024M 

B. 关闭不必要的缓存功能

如果不需要某些高级功能,可以关闭以节省内存:

[mysqld]
# 禁止使用线程缓存(如果并发不高)
thread_cache_size = 0 

# 如果不需要查询缓存(MySQL 8.0 已移除,5.7 及以前慎用)
query_cache_type = 0
query_cache_size = 0

C. 调整其他关键参数

  • max_connections:如果连接数很大,每个连接都会占用内存。如果业务允许,适当降低最大连接数。
  • sort_buffer_size, read_buffer_size 等:这些是每个连接会话级别的内存,如果设置过大且连接数多,会瞬间吃光内存。建议设为较小值(如 1M-4M),除非你有明确的性能瓶颈分析。
[mysqld]
max_connections = 100
sort_buffer_size = 1M
read_buffer_size = 1M

3. 验证与生效

修改配置后,必须重启 MySQL才能生效:

sudo systemctl restart mysql

重启后,进入 MySQL 命令行检查实际占用:

mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
mysql> SHOW STATUS LIKE 'Threads_connected';

同时观察服务器整体内存使用情况:

free -h
top

4. 进阶优化建议

  • 开启 Swap(交换分区)
    如果物理内存实在紧张,可以添加一个 Swap 文件作为“防崩溃”手段(虽然速度慢,但能防止 OOM 杀进程)。

    # 创建 2G swap 文件示例
    sudo fallocate -l 2G /swapfile
    sudo chmod 600 /swapfile
    sudo mkswap /swapfile
    sudo swapon /swapfile
    
    # 设置 swappiness 为 10(让系统优先用物理内存,只有快满了才用 swap)
    echo vm.swappiness=10 | sudo tee -a /etc/sysctl.conf
  • 监控告警
    安装 htop 或使用云厂商自带的监控面板,设置内存使用率超过 80% 时发送报警。

总结

绝大多数情况下,将 innodb_buffer_pool_size 从默认的自动计算(往往过大)手动固定为物理内存的 50% 左右,即可解决内存爆满问题。如果调整后仍然内存不足,请检查是否有慢查询导致大量临时表生成,或考虑升级服务器配置。