不必物理删除swap分区,但必须将vm.swappiness设为10(非0)以平衡性能与稳定性;同时严格限制innodb_buffer_pool_size不超过物理内存50%,并确保mysqld RSS远低于free -h中的available值。

MySQL 本身不支持、也不需要“独立 Swap 分区”——Swap 是操作系统级的内存回退机制,对所有进程一视同仁。所谓“给 MySQL 配独立 Swap”,本质是误读。真正该做的是:让系统有合理 Swap,并调低 MySQL 被 OOM Killer 杀死的概率,同时压住 MySQL 自身内存申请上限。
怎么确认真是 OOM Killer 干的?别猜,直接看内核日志
MySQL 突然消失,不是 mysqld 主动退出,大概率是被内核干掉的。验证方法只有一条:
- 运行
sudo dmesg -T | grep -i "killed process" | grep mysqld,如果有输出,且含total-vm、anon-rss字段,时间点和 MySQL 停止吻合,就是它 - 同时查
free -h:如果available接近 0(比如只剩 100MB),但free列还有几百 MB,这就是典型假象——内核已无页可分配,OOM 已触发 - 注意:
available值才是 MySQL 能安全使用的内存上限,不是总内存,也不是free
Swap 文件 or 分区?小内存机器优先用文件,别碰 dd
现代 Linux 支持 swapfile 和 swap partition 两种形式。对 MySQL 服务器来说,swapfile 更实用:
- OVZ 架构(如部分低价 VPS)不支持 swap,跳过这步;其余情况建议设为物理内存的 1.5 倍(如 2GB 内存配 3G swapfile),上限不超过 4G
- 创建命令必须用
fallocate -l 3G /swapfile,别用dd if=/dev/zero of=/swapfile bs=1M count=3072——太慢,还容易卡住 - 后续三步不能少:
chmod 600 /swapfile→mkswap /swapfile→swapon /swapfile - 写入
/etc/fstab:追加一行/swapfile none swap sw 0 0,否则重启失效
为什么调低 oom_score_adj 效果很有限?
给 mysqld 进程设 oom_score_adj = -500,只是让它比 Nginx、PHP-FPM 更晚被杀——但当系统真缺内存时,它仍是最大 RSS 进程,迟早躺平。
- 真正起效的是压住
innodb_buffer_pool_size:设为物理内存的 50% 以内(2GB 机器设 1G),单位写1G,别写1024M(MySQL 8.0+ 对单位敏感) - 关掉两个吃内存的默认行为:
innodb_buffer_pool_dump_at_shutdown = OFF和innodb_buffer_pool_load_at_startup = OFF - 删旧日志文件:
rm /www/server/mysql/data/ib_logfile*,再重启 MySQL,否则innodb_log_file_size调大后无法生效 - swap 和
oom_score_adj是兜底手段,核心永远是 buffer pool 是否超支、是否匹配free -h中的available值
swappiness=10 是关键阈值,别设成 0
很多人以为 swappiness=0 能“彻底禁用 swap”,其实它只是禁止匿名页换出,但会加剧 page cache 压力,反而更快触发 OOM。
- MySQL 专用服务器建议设
vm.swappiness = 10:既避免频繁 swap 影响性能,又保留紧急回退能力 - 设完执行
sudo sysctl vm.swappiness=10,并写入/etc/sysctl.conf持久化 - 注意:swap 不是救命稻草,而是防止偶发峰值导致服务雪崩的安全网;它救不了长期内存泄漏或 buffer_pool 设置严重超标
最易被忽略的一点:MySQL 的实际 RSS 占用(用 ps -o pid,rss,comm -C mysqld 查)必须明显低于系统 available 值——这个差额,要能覆盖 PHP-FPM、Nginx、监控 agent 等其他进程的常驻开销。算错这一点,swap 再大也白搭。


















