在 1 核 1G 的云服务器上部署 MySQL,内存资源非常紧张,默认配置极易触发 OOM(Out Of Memory)。以下是针对该环境的优化方案,按优先级排序:
✅ 核心原则:限制 MySQL 最大内存占用
MySQL 默认会尝试使用大量内存(如 innodb_buffer_pool_size 默认为物理内存的 50%~75%),在 1G 机器上直接导致 OOM。
🔧 关键优化步骤
1. 调整 my.cnf / mysql.cnf 配置文件
编辑 /etc/my.cnf 或 /etc/mysql/my.cnf,在 [mysqld] 段添加/修改以下参数:
[mysqld]
# 基础设置
max_connections = 20 # 降低并发连接数(默认 151)
thread_cache_size = 4 # 减少线程缓存开销
# InnoDB 缓冲池(最关键!)
innodb_buffer_pool_size = 256M # 建议设为 25%~30% 物理内存(1G → 256M~300M)
innodb_log_file_size = 64M # 日志文件大小(默认可能过大)
innodb_flush_method = O_DIRECT # 避免双重缓冲,减少内存压力
# 其他内存相关
tmp_table_size = 16M # 临时表最大内存大小
max_heap_table_size = 16M # 同上
sort_buffer_size = 1M # 排序缓冲区(默认 2M+,可降)
read_buffer_size = 1M # 顺序读缓冲区
read_rnd_buffer_size = 512K # 随机读缓冲区
join_buffer_size = 1M # JOIN 缓冲区(默认 4M+)
# 关闭不必要功能
skip-name-resolve # 禁用 DNS 反向解析(提升启动速度 & 减少网络请求)
log_queries_not_using_indexes = OFF # 仅记录慢查询(可选)
# 安全限制
performance_schema = OFF # 性能监控消耗内存,生产小机可关闭
💡 注意:所有
*_buffer_size类参数是每个连接独占的,务必调低;而innodb_buffer_pool_size是全局共享的,可相对保留更多。
2. 启用 Swap(虚拟内存)
即使有 Swap,MySQL 仍可能因 oom_score_adj 被杀,但能争取时间并防止系统崩溃:
# 创建 512M~1G swap 文件
sudo fallocate -l 512M /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 永久生效
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# 调整内核参数:允许 MySQL 使用 Swap(谨慎)
sudo sysctl vm.swappiness=10 # 值越小越倾向用物理内存(推荐 1~10)
⚠️ 若仍频繁 OOM,可尝试提高 MySQL 进程 OOM 优先级(使其更难被杀):
# 查看当前 PID
ps aux | grep mysql
# 假设 PID 为 1234
echo -1000 | sudo tee /proc/1234/oom_score_adj
# 或写入 systemd 服务(若用 systemd)
3. 监控与诊断
- 实时内存监控:
free -h top -o %MEM - MySQL 内部内存统计:
SHOW STATUS LIKE 'Innodb_buffer_pool%'; SHOW VARIABLES LIKE '%buffer%'; SHOW PROCESSLIST; -- 查是否有大查询/长事务 - 慢查询日志开启(避免全表扫描拖垮内存):
slow_query_log = 1 slow_query_log_file = /var/log/mysql/slow.log long_query_time = 2 log_queries_not_using_indexes = 1
4. 应用层优化(同等重要)
- 避免
SELECT *,只查必要字段; - 加索引覆盖常用查询;
- 控制单次查询返回行数(
LIMIT); - 使用连接池(如 HikariCP),避免短连接频繁创建销毁;
- 定期清理大表、归档历史数据。
📊 参考配置示例(1C1G 实测可用)
[mysqld]
user=mysql
pid-file=/var/run/mysqld/mysqld.pid
socket=/var/run/mysqld/mysqld.sock
port=3306
basedir=/usr
datadir=/var/lib/mysql
tmpdir=/tmp
skip-name-resolve
max_connections=20
innodb_buffer_pool_size=256M
innodb_log_file_size=64M
innodb_flush_method=O_DIRECT
tmp_table_size=16M
max_heap_table_size=16M
sort_buffer_size=1M
read_buffer_size=1M
read_rnd_buffer_size=512K
join_buffer_size=1M
performance_schema=OFF
thread_cache_size=4
重启后验证:
systemctl restart mysqld
free -h
mysql -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"
⚠️ 最后建议
如果业务负载较重(如高频写入、复杂 JOIN、大结果集),1C1G 已接近 MySQL 运行底线。长期方案应考虑:
- 升级到 2C2G(成本增加有限,稳定性显著提升);
- 或改用轻量级数据库(如 SQLite + 读写分离、Redis 做缓存层减轻 DB 压力);
- 或使用云厂商的 Serverless MySQL(按需计费,自动扩缩容)。
需要我帮你生成完整的 my.cnf 文件或分析具体慢查询吗?
轻量云Cloud