在 1 核 1G(1GB)内存的云服务器上运行 MySQL,内存资源非常紧张,必须对默认配置进行深度优化。MySQL 默认配置通常是为多核多内存服务器设计的,直接运行会导致频繁的 Swap 交换甚至 OOM(Out of Memory)崩溃。
以下是针对该场景的核心优化策略和具体配置建议:
1. 核心参数调整 (my.cnf / my.ini)
这是最关键的一步。你需要修改 MySQL 的配置文件(通常在 /etc/my.cnf),将以下关键参数限制在合理范围内,确保 MySQL 进程本身占用不超过 600MB-700MB,为操作系统和其他进程留出空间。
请在 [mysqld] 段落下添加或修改以下内容:
[mysqld]
# 基础设置
user = mysql
basedir = /usr
datadir = /var/lib/mysql
port = 3306
socket = /tmp/mysql.sock
# --- 内存优化核心参数 ---
# 1. 连接缓冲区 (每个连接独立)
# 1G 内存建议设为 128K - 256K。如果并发高,适当调大,但切勿过大。
max_connections = 50
thread_stack = 192K
thread_cache_size = 8
# 2. 查询缓存 (注意:MySQL 8.0+ 已移除 query cache,如果是 5.7 可开启,否则忽略)
# 如果版本是 5.7 且业务读多写少,可开启;如果是 8.0 则无需配置
query_cache_type = 0
# query_cache_size = 64M
# 3. InnoDB 缓冲池 (最重要的内存占用项)
# 建议设置为总内存的 50%-60%,即 300M - 400M
# 必须小于 512M,防止系统 OOM
innodb_buffer_pool_size = 300M
innodb_log_file_size = 64M
innodb_flush_method = O_DIRECT
# 4. 临时表与排序
# 控制临时表大小,避免溢出到磁盘
tmp_table_size = 64M
max_heap_table_size = 64M
# 5. 其他关键参数
sort_buffer_size = 256K # 单个排序操作
read_buffer_size = 256K
read_rnd_buffer_size = 256K
join_buffer_size = 256K
# 6. 日志与超时
log_error = /var/log/mysqld.log
slow_query_log = 1
slow_query_log_file = /var/log/mysql-slow.log
long_query_time = 2
重要提示:
- InnoDB Buffer Pool Size: 这是最大的开销。如果只跑一个库,设为
300M比较安全;如果有多个库且数据量小,可适当降低至256M。 - Max Connections: 1G 内存下,不要设置成默认的 151。建议设为
50左右。如果应用端有连接池,确保连接池大小也匹配这个值。
2. 关闭不必要的功能与服务
- 禁用 Query Cache (MySQL 5.7): 在高并发写入场景下,Query Cache 反而会成为锁竞争点,且维护它消耗 CPU 和内存。如果不需要,直接关闭。
- 关闭慢查询日志 (可选): 如果磁盘 I/O 压力大,可以暂时关闭
slow_query_log,或者仅在生产环境开启并定期清理。 - 停止多余服务: 确保云主机上没有运行其他重型数据库(如 PostgreSQL、MongoDB)或图形界面服务。
3. 操作系统层面的优化
Linux 内核参数也需要配合调整,以应对内存压力:
A. 禁用 Swap 或谨慎使用 Swap
虽然 Swap 能防止立即崩溃,但在 1G 内存机器上,频繁使用 Swap 会导致性能急剧下降(IO 瓶颈)。
- 方案一(推荐):完全禁用 Swap,依靠严格的内存限制防止 OOM。
swapoff -a # 编辑 /etc/fstab 注释掉 swap 分区行 - 方案二:保留少量 Swap 作为最后的防线,但调整 Swappiness。
# 让系统尽量少用 Swap,优先杀掉进程而不是卡死 sysctl vm.swappiness=1
B. 调整透明大页 (Transparent Huge Pages, THP)
THP 在某些场景下会消耗额外内存并导致延迟抖动。对于 MySQL,建议关闭。
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
# 将其加入开机启动脚本
C. 增加虚拟内存(Swap)作为“保险”
如果你担心完全无 Swap 会导致 MySQL 进程被 Linux OOM Killer 直接杀掉(虽然这比卡顿好,但可能导致服务不可用),可以创建一个较小的 Swap 文件(例如 512MB),但务必配合低 swappiness。
4. 数据库设计与 SQL 优化
硬件受限,软件设计必须跟上:
- 索引优化: 确保所有
WHERE,JOIN,ORDER BY字段都有合适的索引。避免全表扫描,因为全表扫描会大量占用 Buffer Pool 并产生临时表。 - 减少临时表: 检查慢查询日志,优化那些生成大量临时表的 SQL(如复杂的
GROUP BY或DISTINCT)。 - 数据类型最小化: 尽量使用
TINYINT,SMALLINT,VARCHAR(长度)等合适类型,减少单行数据的存储体积,从而在同样的 Buffer Pool 中容纳更多热点数据。 - 字符集: 如果使用
utf8mb4,每个字符最多占 4 字节,开销较大。如果业务允许,考虑使用latin1或gbk(需评估兼容性)。
5. 监控与运维建议
- 监控工具: 安装
htop或glances实时监控内存和 Swap 使用情况。free -h - 自动重启脚本: 编写一个简单的守护脚本,检测 MySQL 是否存活,一旦崩溃尝试自动重启。
- 备份策略: 由于内存小,全量备份可能会瞬间吃光内存。建议使用
mysqldump --single-transaction并结合--quick选项,或者使用物理备份工具(如 Percona XtraBackup)的小规模增量备份。
总结配置示例 (/etc/my.cnf 片段)
[mysqld]
# 核心限制
innodb_buffer_pool_size = 300M
max_connections = 50
thread_cache_size = 8
table_open_cache = 200
# 单次操作限制
sort_buffer_size = 256K
read_buffer_size = 256K
read_rnd_buffer_size = 256K
join_buffer_size = 256K
tmp_table_size = 64M
max_heap_table_size = 64M
# 性能与稳定性
skip-name-resolve = 1
local-infile = 0
log-error = /var/log/mysqld.log
slow_query_log = 1
long_query_time = 2
通过以上配置,你可以将 MySQL 的内存占用控制在 600MB 以内,预留约 400MB 给操作系统内核缓存和应用程序,从而在 1G 内存的云主机上实现稳定运行。
PHPWP博客