2 核 4G 的服务器属于典型的“小马拉大车”场景。MySQL 吃内存,Nginx 吃连接数和上下文切换,两者同时跑,核心矛盾就是内存争抢。一旦内存爆满触发 OOM Killer(系统自动杀进程),服务就会直接挂掉。
优化思路不是“调参”,而是“做减法”和“精准分配”。以下是针对该配置的具体实操方案:
一、MySQL 参数调优(核心是限流)
在 4G 总内存下,MySQL 绝对不能吃撑,必须给操作系统和 Nginx 留足余地。建议预留 1.5G – 1.8G 给系统和 Nginx,留给 MySQL 的 innodb_buffer_pool_size 最多只能给到 2G,甚至保守点给 1.5G。
-
缓冲池大小 (
innodb_buffer_pool_size)- 设置:
2G(即2147483648)。 - 理由:这是 MySQL 性能的灵魂。如果设太大,系统内存不足会疯狂 Swap,导致磁盘 IO 飙升,数据库卡死;设太小,命中率低,CPU 空转。2G 对于 2 核机器是安全线。
- 设置:
-
连接数限制 (
max_connections)- 设置:
100~150。 - 理由:默认通常是 151,但在低配机器上,每个连接都要占用线程栈(约几 MB)。如果并发高,大量连接会导致内存瞬间耗尽。配合 Nginx 做反向X_X后,后端数据库通常不需要处理海量直连,压到 150 以内足够。
- 设置:
-
查询缓存 (
query_cache_type&query_cache_size)- 设置:彻底关闭。
- 操作:
SET GLOBAL query_cache_type = 0;并在配置文件中注释掉相关行。 - 理由:MySQL 5.7+ 已废弃此功能,且在高并发下会产生严重的锁竞争。在 2 核机器上,它带来的性能损耗远大于收益。
-
临时表与排序 (
tmp_table_size/max_heap_table_size)- 设置:
64M~128M。 - 理由:防止复杂的 SQL 将大量数据写入内存临时表,进而溢出到磁盘。这两个值设大了,容易占满剩余内存;设小了,频繁落盘又慢。64M-128M 是个折中。
- 设置:
-
日志与事务 (
binlog_cache_size,sync_binlog)- 设置:
binlog_cache_size设为32K或64K(默认即可)。 - 注意:如果是主从架构,
sync_binlog=1最安全但最慢;如果是单库非关键业务,可考虑sync_binlog=0换取速度,但需接受少量数据丢失风险。对于 2 核机器,IO 瓶颈通常在磁盘,减少刷盘频率能缓解压力。
- 设置:
二、Nginx 参数调优(核心是并发与缓冲区)
Nginx 本身很轻量,但在 2 核 CPU 下,主要怕的是Worker 进程过多导致上下文切换,以及Buffer 过大导致内存泄漏。
-
工作进程数 (
worker_processes)- 设置:
auto或明确指定为2。 - 理由:物理核数是 2,开启 2 个 Worker 是最优解。开多了(如 4 个以上)会导致 CPU 在不同进程间频繁切换,反而降低吞吐。
- 设置:
-
最大连接数 (
worker_connections)- 设置:
1024或2048。 - 理由:不要盲目开到 65535。2 核 CPU 处理不了那么高的并发连接数,过高的数值只会增加内核调度负担。结合
multi_accept on使用效果更好。
- 设置:
-
客户端缓冲区 (
client_body_buffer_size,proxy_buffer_size)- 设置:
client_body_buffer_size设为16k或32k;proxy_buffer_size设为4k或8k。 - 理由:默认值往往偏大。如果请求体很大,Nginx 会尝试把整个包读入内存再转发。在 4G 内存服务器上,一旦遇到大文件上传或长报文,几个大请求就能把内存吃光。适当调小,迫使 Nginx 尽快将数据写入临时磁盘文件(/var/lib/nginx/tmp),以空间换内存稳定性。
- 设置:
-
超时时间 (
proxy_read_timeout,send_timeout)- 设置:根据业务调整,建议
60s左右。 - 理由:防止某个慢请求长时间占用连接资源,拖垮整个 Nginx 队列。
- 设置:根据业务调整,建议
三、操作系统层面的关键动作
除了软件配置,Linux 内核参数对这种小规格机器至关重要:
-
关闭 Swap(虚拟内存)
- 操作:
swapoff -a并注释/etc/fstab中的 swap 分区。 - 理由:很多人以为有 Swap 就安全了,其实对于 MySQL,Swap 是灾难。一旦开始 Swap,磁盘 IO 会被瞬间打满,响应时间从毫秒级变成秒级甚至分钟级,直接雪崩。宁可让 OOM Killer 杀掉一个进程,也不要让系统进入 Swap 状态。
- 操作:
-
TCP 内核参数优化
- 操作:修改
/etc/sysctl.conf。 - 关键项:
net.core.somaxconn = 1024(提高监听队列长度)net.ipv4.tcp_max_syn_backlog = 2048net.ipv4.ip_local_port_range = 1024 65535net.ipv4.tcp_tw_reuse = 1(允许重用 TIME_WAIT socket)
- 理由:解决高并发下端口耗尽或连接建立失败的问题。
- 操作:修改
-
文件描述符限制 (
ulimit)- 操作:在
/etc/security/limits.conf中,将nproc和nofile都调大到65535。 - 理由:Nginx 和 MySQL 都需要打开大量文件/socket,默认限制(通常是 1024)在稍微有点流量时就会报错 "Too many open files"。
- 操作:在
四、总结与兜底策略
在 2 核 4G 的环境下,没有完美的参数,只有妥协的方案。
- 优先级:先保 MySQL 不崩(限制 Buffer Pool),再保 Nginx 不卡(限制连接和 Buffer),最后靠 OS 层切断 Swap。
- 监控:务必安装
htop或 Prometheus + Grafana。重点观察Mem的使用率和Swap是否被触发。 - 应用侧:代码层面必须做好索引优化。2 核机器跑不动全表扫描,一条没索引的 SQL 就能把 CPU 跑满。
如果经过上述优化,依然出现频繁 OOM 或 CPU 100%,说明硬件确实无法满足当前业务负载。这时候唯一的出路是:升级硬件或者拆分服务(例如把 MySQL 迁移到独立的高配实例,这台只跑 Nginx 和静态资源)。
云知道CLOUD