运行 MySQL 8.0 的服务器,swap 分区是否必须关闭?如何设置 vm.swappiness?

服务器

在运行 MySQL 8.0(尤其是生产环境)的 Linux 服务器上,swap 分区不强制要求“关闭”(即完全禁用),但强烈建议禁用 swap 或将其影响降至最低,并将 vm.swappiness 设置为极低值(通常 10。原因如下:


✅ 为什么需要严格控制 swap?

MySQL 是内存密集型应用,尤其依赖 Buffer Pool(默认可占物理内存 50–80%)。若系统发生内存压力:

  • Swap 会导致灾难性性能下降:InnoDB 页面被换出到磁盘(swap)后,再访问时需从慢速磁盘换入,延迟从纳秒级升至毫秒级(>10⁶ 倍),引发查询雪崩、连接堆积、甚至主从延迟失控。
  • OOM Killer 风险增加:当内存严重不足时,内核可能优先杀死 MySQL 进程(而非其他轻量进程),导致服务中断。
  • MySQL 自身无 swap 意识:它假设内存访问是快速的,不会主动规避 swap;而 swap 是透明的,对应用不可见但危害巨大。

📌 官方建议(MySQL 8.0 Reference Manual – Optimizing for InnoDB)明确指出:
“Ensure that the system does not swap out the MySQL process. If necessary, set vm.swappiness=0.”


✅ 推荐配置方案(生产环境)

项目 推荐值 说明
vm.swappiness 1(首选)或 0 1 允许内核仅在极端内存耗尽时(如只剩几 MB 可用)才 swap,兼顾稳定性与安全;0 禁止 swap(但 Linux 4.12+ 中 0 仍可能 swap 大页/匿名内存,1 更稳妥)
Swap 分区 禁用(swapoff -a + /etc/fstab 注释) 彻底消除 swap 风险;若合规/运维策略要求保留 swap(如某些云平台或 HA 环境),则必须配合 swappiness=1 + 严格监控
内存预留 为 OS 保留 ≥ 2–4 GB(即使 64G+ 内存) 避免 Buffer Pool 占满全部内存,留出空间给文件缓存、网络栈、OS 进程等

🔧 如何设置(永久生效)

1. 临时设置(立即生效)

# 查看当前值
cat /proc/sys/vm/swappiness

# 设置为 1(推荐)
sudo sysctl vm.swappiness=1

# 验证
echo $(( $(grep -i "memavailable" /proc/meminfo | awk '{print $2}') / 1024 ))  # MB 可用内存(确保充足)

2. 永久设置(重启后保持)

# 编辑 sysctl 配置
echo 'vm.swappiness = 1' | sudo tee -a /etc/sysctl.conf

# 或创建专用配置文件(更清晰)
echo 'vm.swappiness = 1' | sudo tee /etc/sysctl.d/99-mysql-swappiness.conf

# 重载配置
sudo sysctl --system

3. 禁用 Swap(推荐)

# 临时禁用所有 swap
sudo swapoff -a

# 永久禁用:注释 /etc/fstab 中 swap 行(如 UUID=... none swap sw 0 0)
sudo sed -i '/swap/s/^/#/' /etc/fstab

# 验证
free -h  # 应显示 Swap: 0B
swapon --show  # 应无输出

⚠️ 注意:若使用 LVM 或加密 swap,需额外处理(如 lvremove 或修改 /etc/crypttab)。


📊 额外关键优化(协同生效)

  • 限制 MySQL 内存使用
    my.cnf 中显式设置:

    [mysqld]
    innodb_buffer_pool_size = 4G     # 建议设为物理内存的 50–75%,留足 OS 内存
    innodb_log_file_size = 256M
    max_connections = 200            # 避免连接数过多耗尽内存
  • 监控内存压力
    # 检查是否发生 swap(理想应为 0)
    grep -i "swapped" /proc/vmstat  # 或 watch -n 1 'free -h; cat /proc/vmstat | grep pgpg'
    # 使用 atop/top 观察 `SWAP` 列和 `MEM` 使用率

❌ 常见误区澄清

误区 正解
“有足够内存就不需要关 swap” 即使内存充足,内核仍可能因内存碎片、cgroup 限制、或突发负载触发 swap,且 MySQL 对延迟极度敏感
swappiness=0 就绝对安全” Linux 4.12+ 后 0 仍可能 swap 匿名页面(如大块 malloc),1 是更可靠的选择(Kernel Docs)
“云服务器(如 AWS/Azure)必须保留 swap” 云平台通常允许禁用 swap;若强制要求(如某些托管数据库),则必须配 swappiness=1 + 实时监控 swap 使用率

✅ 总结建议

场景 推荐操作
生产 MySQL 8.0 服务器 ✅ 禁用 swap (swapoff -a + 注释 fstab) + vm.swappiness=1 + innodb_buffer_pool_size 合理限制
测试/开发环境 可保留 swap,但 swappiness=1 仍推荐
无法禁用 swap 的受限环境 必须设 swappiness=1 + 部署告警(当 cat /proc/swaps 非空或 vmstat 1 显示 si/so > 0 时告警)

💡 最终目标:让 MySQL 的内存访问始终落在 RAM 中,避免任何 swap 引入的不可预测延迟。

如需进一步检查 MySQL 内存配置合理性,可提供 SHOW VARIABLES LIKE '%buffer%';free -h 输出,我可帮你分析优化空间。

未经允许不得转载:CDNK博客 » 运行 MySQL 8.0 的服务器,swap 分区是否必须关闭?如何设置 vm.swappiness?