CentOS或Ubuntu 2G内存服务器部署MySQL后经常OOM,怎么调优?

在2GB内存的服务器上部署MySQL确实容易遇到OOM问题。以下是一套完整的调优方案:

1. 核心参数优化(my.cnf/my.ini)

[mysqld]
# 基础设置
innodb_buffer_pool_size = 256M  # 关键!不要超过总内存的50%
key_buffer_size = 32M
max_connections = 50  # 减少并发连接数
thread_cache_size = 8
table_open_cache = 256

# InnoDB优化
innodb_log_file_size = 64M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 2  # 平衡性能和数据安全
innodb_file_per_table = ON
innodb_flush_method = O_DIRECT

# 查询缓存(MySQL 8.0已移除,5.7可谨慎使用)
# query_cache_type = 0  # 建议关闭,避免内存竞争

# 临时表
tmp_table_size = 32M
max_heap_table_size = 32M

# 连接和线程
thread_stack = 256K
sort_buffer_size = 2M
read_buffer_size = 1M
read_rnd_buffer_size = 1M
join_buffer_size = 1M

2. 操作系统级优化

调整SWAP空间(确保有备用交换空间)

# 检查当前swap
free -h

# 创建swap文件(如果不足)
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# 永久生效
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

调整内核参数

# 编辑 /etc/sysctl.conf
vm.swappiness = 10  # 降低swap使用倾向
vm.overcommit_memory = 0  # 保守的内存分配策略
vm.overcommit_ratio = 50

# 生效配置
sysctl -p

3. MySQL监控与诊断

查看内存使用情况

-- 查看当前内存分配
SHOW VARIABLES LIKE '%buffer%';
SHOW VARIABLES LIKE '%cache%';

-- 查看内存使用统计
SELECT * FROM sys.memory_global_total;
SELECT * FROM sys.memory_by_thread_by_current_bytes LIMIT 10;

识别内存消耗大的连接

-- 查看连接内存使用(MySQL 5.7+)
SELECT 
    thread_id,
    user,
    current_allocated
FROM sys.memory_by_thread_by_current_bytes 
ORDER BY current_allocated DESC 
LIMIT 10;

4. 应用层优化建议

连接池配置

# 在应用连接池中设置
maxActive=20           # 最大连接数
maxIdle=10             # 最大空闲连接
minIdle=5              # 最小空闲连接
testOnBorrow=true      # 验证连接有效性

定期维护

# 设置定时任务清理
# 每天凌晨优化表
0 3 * * * mysqlcheck -o --all-databases

# 定期分析慢查询日志
pt-query-digest /var/log/mysql/mysql-slow.log

5. 应急措施

当出现OOM时:

  1. 立即重启MySQL并调整参数

    sudo systemctl restart mysql
  2. 使用内存限制工具

    # 使用systemd限制内存
    # 编辑 /etc/systemd/system/mysql.service.d/limits.conf
    [Service]
    MemoryLimit=1.5G
  3. 考虑轻量级替代方案

    • MariaDB(更轻量)
    • PostgreSQL(内存管理更好)
    • SQLite(适合小型应用)

6. 监控告警设置

# 安装监控工具
# CentOS
sudo yum install -y htop atop

# Ubuntu
sudo apt install -y htop atop

# 设置监控脚本
cat > /usr/local/bin/check_mysql_mem.sh << 'EOF'
#!/bin/bash
MEM_USED=$(free -m | awk '/Mem:/ {print $3}')
MEM_TOTAL=$(free -m | awk '/Mem:/ {print $2}')
MEM_PERCENT=$((MEM_USED*100/MEM_TOTAL))

if [ $MEM_PERCENT -gt 85 ]; then
    echo "警告:内存使用率 ${MEM_PERCENT}%"
    # 发送告警邮件或通知
fi
EOF
chmod +x /usr/local/bin/check_mysql_mem.sh

7. 长期解决方案建议

  1. 升级硬件:至少升级到4GB内存
  2. 使用云数据库:如AWS RDS、阿里云RDS等托管服务
  3. 分库分表:减少单实例压力
  4. 读写分离:主库写,从库读
  5. 使用缓存层:如Redis缓存热点数据

关键原则:

  • innodb_buffer_pool_size 不要超过总内存的50%
  • 监控 实际内存使用,而非仅看配置值
  • 定期分析 慢查询,优化SQL语句
  • 考虑 数据归档,删除不必要的历史数据

根据你的具体使用场景(OLTP还是OLAP),可能需要进一步调整。建议先在测试环境验证配置,再应用到生产环境。

云服务器