在运行 MySQL 8.0(尤其是高负载、OLTP 场景)的生产服务器上,强烈建议关闭 swap 分区或将其影响降至最低,但“必须关闭”需结合具体场景审慎判断。更准确的说法是:应避免 MySQL 工作集被换出(swapped out),因此需通过合理配置 vm.swappiness 和内存规划来实现,而非绝对禁用 swap。
以下是专业、可落地的建议:
✅ 一、为什么 swap 对 MySQL 不友好?
- MySQL(尤其 InnoDB)严重依赖内存缓存(
innodb_buffer_pool_size),其性能对内存延迟极度敏感。 - 若 buffer pool 或热点数据页被 swap 到磁盘,一次逻辑读可能触发 毫秒级 swap I/O(甚至百毫秒),远超 SSD 的微秒级随机读,导致查询雪崩、连接堆积、主从延迟激增。
- Linux OOM Killer 可能在内存压力下优先 kill mysqld 进程(因其内存占用大),而非其他小进程。
⚠️ 注意:swap 并非“完全无用”。它在以下场景仍有价值:
- 防止突发内存泄漏/异常导致 OOM Kill(提供缓冲时间);
- 支持 hibernation(休眠);
- 容器环境(如 Docker/K8s)中,swap 可辅助资源隔离(但需谨慎启用)。
✅ 二、vm.swappiness 推荐设置(关键!)
| 场景 | vm.swappiness 值 |
说明 |
|---|---|---|
| 专用 MySQL 服务器(物理机 / 虚拟机,内存充足) | 1(✅ 最佳实践) |
极小化主动 swap,仅在内存真正耗尽时才考虑 swap;保留系统稳定性,避免 OOM Kill。 |
内存严重受限(如 innodb_buffer_pool_size > 80% RAM)且无法扩容 |
0 |
禁用 主动 swap(内核不主动换出匿名页),但 仍允许 swap 用于紧急内存分配(如 mmap(MAP_ANONYMOUS) 失败时)和 THP 退化等。⚠️ 注意: swappiness=0 ≠ swap 被禁用(swap 分区仍可被使用,例如 kswapd 在极端 OOM 时仍可能换出) |
| 多用途服务器(MySQL + 其他服务)或云环境(如 AWS EC2) | 1 ~ 10 |
平衡稳定性与性能,避免 MySQL 内存被轻易换出。 |
| 绝对禁止 swap(测试/特殊合规要求) | 0 + swapoff -a + /etc/fstab 注释 swap 行 |
✅ 彻底禁用,但失去最后防线,OOM 风险升高。 |
❌ 不要设为 60(默认值)或更高 —— 这会显著增加 MySQL 页面被换出的概率。
🔧 如何设置(永久生效):
# 1. 临时生效(重启前有效)
sudo sysctl vm.swappiness=1
# 2. 永久生效:编辑 /etc/sysctl.conf
echo 'vm.swappiness=1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
# 3. (可选)验证当前值
cat /proc/sys/vm/swappiness
✅ 三、配套最佳实践(比单纯调 swappiness 更重要!)
-
合理规划内存
innodb_buffer_pool_size建议设为 物理内存的 50%–75%(专用服务器),确保 OS 缓存、文件系统、连接线程等有足够空间。- 避免过度分配(如设为 90%+),否则 OS 内存不足 → kswapd 活跃 → swap 风险上升。
-
监控 swap 使用
# 实时查看 swap 使用(重点关注 si/so 列) vmstat 1 5 # si: swap-in KB/s, so: swap-out KB/s → 理想值应长期为 0 # 查看 MySQL 进程是否被 swap sudo cat /proc/$(pgrep -f "mysqld")/status | grep -i "swap" # 或使用 smaps(更详细) sudo awk '/^Swap:/ {swap+=$2} END{print "Total swap used by mysqld: " swap " KB"}' /proc/$(pgrep -f "mysqld")/smaps -
禁用透明大页(THP)(MySQL 8.0 强烈要求)
# 临时禁用 echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled # 永久禁用(添加到 /etc/rc.local 或 systemd service) -
使用 cgroups v2(现代 Linux)限制 MySQL 内存上限(防内存溢出)
# 示例:限制 mysqld 最多使用 32GB 内存(含 swap) sudo systemctl set-property mysqld.service MemoryMax=32G
✅ 四、结论(一句话总结)
MySQL 8.0 生产服务器不应依赖 swap,而应通过
vm.swappiness=1+ 合理innodb_buffer_pool_size+ 监控 + THP 禁用,确保工作集常驻物理内存;swap 分区可保留但应几乎不被使用——这不是“必须关闭”,而是“必须使其失效于 MySQL 性能路径”。
如需进一步优化,可提供您的:
- 服务器内存总量 &
innodb_buffer_pool_size设置 free -h和vmstat 1 5输出- MySQL 错误日志中是否有
Out of memory或swap相关警告
我可以帮您做针对性诊断 👍
✅ 参考来源:MySQL 官方文档(Optimizing for InnoDB)、Percona 最佳实践、Linux 内核文档(Documentation/admin-guide/mm/swap.rst)。
CLOUD技术博