在 2核4GB 内存 的服务器上同时运行 MySQL(作为数据库)和 Nginx(作为 Web 服务器/反向X_X),属于典型的轻量级生产或中高流量测试环境。资源有限,必须精细协调,避免内存争抢(尤其是 MySQL 的内存占用容易“吃光”系统内存导致 OOM Kill),同时兼顾响应性能与稳定性。
以下是关键优化方向及具体参数建议(基于主流 Linux 发行版 + MySQL 8.0+ / Nginx 1.18+):
✅ 一、全局前提:系统级基础优化
| 项目 | 建议 | 说明 |
|---|---|---|
| 禁用 swap(或严格限制) | sudo swapoff -a + 注释 /etc/fstab 中 swap 行;或设 vm.swappiness=1 |
防止 MySQL/Nginx 因内存压力被 swap 到磁盘,引发严重延迟甚至崩溃 |
| ulimit 调整 | ulimit -n 65535(永久写入 /etc/security/limits.conf) |
避免 Nginx 连接数/MySQL 文件描述符不足 |
| 时钟同步 | systemctl enable --now chrony |
MySQL 复制、日志时间戳依赖精准时间 |
✅ 二、MySQL 优化(重点:内存控制!)
⚠️ 目标:MySQL 总内存占用 ≤ 1.8–2.2 GB(预留 1.5–2 GB 给 OS + Nginx + 缓冲)
🔹 关键配置(/etc/my.cnf 或 /etc/mysql/mysql.conf.d/mysqld.cnf)
[mysqld]
# —— 内存相关(核心!按实际数据量微调)——
innodb_buffer_pool_size = 1280M # ⭐ 强烈推荐:1.2~1.5G(不超过物理内存的 40%)
innodb_log_file_size = 128M # 日志文件大小(默认 48M → 提升至 128M,减少刷盘频率)
innodb_flush_log_at_trx_commit = 1 # 安全优先(=2 更快但有1秒风险;=0 不推荐)
innodb_flush_method = O_DIRECT # 避免双缓冲(Linux 下推荐)
# —— 连接与线程 ——
max_connections = 150 # 默认151,够用且防爆内存;根据并发调整(可用 `show status like 'Threads_connected';` 观察)
wait_timeout = 300 # 空闲连接超时(秒),及时释放
interactive_timeout = 300
# —— 查询优化 ——
query_cache_type = 0 # ❌ MySQL 8.0+ 已移除,若为 5.7 则设为 0(缓存效率低且易锁表)
tmp_table_size = 32M # 内存临时表上限(与 max_heap_table_size 一致)
max_heap_table_size = 32M
sort_buffer_size = 512K # 每连接排序缓冲(勿设过大!)
read_buffer_size = 256K
read_rnd_buffer_size = 512K
join_buffer_size = 512K
# —— 其他稳健性 ——
innodb_io_capacity = 200 # SSD 设 400~1000;HDD 设 100~200
innodb_io_capacity_max = 2000 # 峰值 IO 能力(SSD 可设 4000)
skip_log_bin # 若无需主从复制,关闭 binlog 节省 I/O 和空间(⚠️ 开启则需额外 ~200MB 内存缓冲)
🔹 必查项:
- ✅ 运行
mysqltuner.pl(Perl 脚本)自动分析:wget https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl perl mysqltuner.pl --user root --pass 'your_pwd' - ✅ 监控内存:
free -h+ps aux --sort=-%mem | head -10查看 mysqld 实际 RSS 占用 - ✅ 关闭无用引擎:
skip-innodb❌(必须启用),skip-myisam✅(MyISAM 基本不用)
✅ 三、Nginx 优化(轻量、高并发)
⚠️ 目标:Nginx 内存占用控制在 300–500 MB 内,支持 2000+ 并发连接
🔹 关键配置(/etc/nginx/nginx.conf)
user www-data;
worker_processes auto; # 自动识别 CPU 核心数(2核 → 2 worker)
worker_cpu_affinity auto; # (可选)绑定 CPU 核心,减少上下文切换
events {
worker_connections 2048; # ⭐ 每 worker 最大连接数(2×2048=4096 总连接)
use epoll; # Linux 高效事件模型
multi_accept on; # 一次接收多个连接
}
http {
include mime.types;
default_type application/octet-stream;
# —— 性能与内存 ——
sendfile on; # 零拷贝传输静态文件
tcp_nopush on; # 合并小包(配合 sendfile)
tcp_nodelay on; # 禁用 Nagle(提升实时性,如 WebSocket)
keepalive_timeout 65; # 连接复用时间(60~75s 合理)
client_header_timeout 10;
client_body_timeout 10;
send_timeout 10;
# —— 缓冲区(关键!防内存暴涨)——
client_header_buffer_size 1k; # 请求头缓冲
large_client_header_buffers 4 4k; # 大请求头(如带长 Cookie)
client_max_body_size 10m; # 上传限制(按需调)
client_body_buffer_size 128k; # 请求体缓冲(内存中)
fastcgi_buffers 8 16k; # PHP-FPM 场景(如有)
fastcgi_buffer_size 32k;
# —— Gzip(降低带宽,略增 CPU)——
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# —— 静态文件缓存(减少磁盘 IO)——
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# —— 其他安全/稳定 ——
reset_timedout_connection on;
server_tokens off;
}
🔹 推荐搭配:
- ✅ 若后端是 PHP-FPM:将
pm.max_children设为30~50(pm = dynamic),避免 fork 过多进程耗尽内存 - ✅ 若用 Node.js/Python:确保其进程数 ≤ 2(如 PM2
--instances 2),并限制内存(--max-memory-restart 800M)
✅ 四、协同与监控(不可少!)
| 工具 | 用途 | 命令示例 |
|---|---|---|
| htop / glances | 实时内存/CPU/进程监控 | htop → 按 F6 → MEM% 排序 |
| mysqladmin | MySQL 状态检查 | mysqladmin processlist -u root -pmysqladmin extended-status -u root -p | grep -i "Threads_connected|Questions" |
| nginx stub_status | Nginx 连接统计 | 在 server 块加 location /nginx_status { stub_status; },然后 curl http://localhost/nginx_status |
| logrotate | 防止日志撑爆磁盘 | 确保 /var/log/nginx/*.log 和 /var/log/mysql/*.log 已配置轮转 |
| systemd 服务内存限制(进阶) | 防止单服务失控 | 在 /etc/systemd/system/mysqld.service.d/override.conf 中添加:[Service]MemoryLimit=2G |
✅ 五、避坑指南(血泪经验)
- ❌ 不要 将
innodb_buffer_pool_size设为2G或更高 → 极易触发 OOM Killer 杀死 mysqld 或 sshd! - ❌ 不要 开启
query_cache(MySQL 5.7)或依赖它 → 锁表严重,8.0 已移除。 - ❌ 不要 让 Nginx
worker_connections过高(如 8192)而忽略ulimit -n未同步 → 导致accept() failed (24: Too many open files)。 - ✅ 务必 使用
sysctl -p加载内核参数(如net.core.somaxconn=65535)。 - ✅ 上线前压测:用
ab或wrk模拟 1000 并发,观察free -h和dmesg -T | tail是否出现Out of memory: Kill process。
✅ 附:快速检查清单(部署后必跑)
# 1. 内存是否健康?
free -h && echo "---" && ps aux --sort=-%mem | head -5
# 2. MySQL 内存估算(近似)
mysql -uroot -p -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"
mysql -uroot -p -e "SHOW VARIABLES LIKE 'max_connections';"
# ≈ buffer_pool + (sort_buffer_size + read_buffer_size) × max_connections
# 3. Nginx 连接数是否合理?
curl -s http://localhost/nginx_status | grep 'Active|Reading'
# 4. 检查 OOM 历史
dmesg -T | grep -i "killed process"
如需进一步定制(例如:你用的是 WordPress?Laravel?还是纯 API 服务?),欢迎补充场景,我可以给出针对性更强的参数(如 PHP-FPM 调优、InnoDB 表压缩、Nginx 缓存策略等)。
需要我帮你生成一份 开箱即用的完整 my.cnf + nginx.conf 配置模板 吗? 😊
云服务器