走啊走
加油

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

服务器价格表

在运行 MySQL 8.0(尤其是生产环境)的 Linux 服务器上,swap 分区不必须物理删除或禁用,但强烈建议关闭 swap 或将其影响降至最低,核心原因在于:MySQL(尤其是 InnoDB)严重依赖内存的确定性访问延迟,而 swap 会引入不可预测的 I/O 延迟和性能抖动,可能导致连接超时、长事务阻塞、甚至服务不可用

不过,是否“必须关闭”需结合场景理性判断。以下是权威建议与实操指南:


✅ 一、为什么建议禁用/最小化 swap?

风险点 说明
性能抖动(Latency Spikes) 当内存压力大时,内核可能将部分 MySQL 内存页(如 innodb_buffer_pool 中的热页)换出到 swap,后续访问触发 page-in,造成数百毫秒~秒级延迟,远超正常磁盘 I/O(通常几 ms)。InnoDB 对延迟敏感,易触发 Lock wait timeoutDeadlock detectedAborted connection
OOM Killer 误杀风险升高 若未禁用 swap,系统在内存耗尽时倾向于 swap 而非直接 OOM Kill;但当 swap 也耗尽时,OOM Killer 可能错误杀死 mysqld 进程(而非其他更安全的进程),导致数据库崩溃。
Buffer Pool 效率下降 InnoDB 的 buffer pool 设计假设内存访问是快速且可预测的。swap 破坏了这一假设,使 LRU 算法失效,缓存命中率骤降。

📌 MySQL 官方文档虽未强制要求禁用 swap,但明确指出
“Swapping can significantly degrade performance. If possible, avoid swapping.”
(来源:MySQL 8.0 Reference Manual - Optimizing for InnoDB)


⚙️ 二、推荐配置:vm.swappiness

含义 适用场景 推荐度
0 内核仅在内存完全耗尽(OOM)时才使用 swap(即:不主动 swap,仅作为最后防线)。
✅ 最佳实践!平衡了稳定性与性能。
生产环境 MySQL 服务器(强烈推荐) ⭐⭐⭐⭐⭐
1 类似 0,但某些内核版本中 0 可能被忽略,1 更可靠(尤其 RHEL/CentOS 7+、Ubuntu 20.04+)。 ✅ 生产环境(保守选择) ⭐⭐⭐⭐⭐
10 较低倾向 swap,但仍可能在内存压力下换出匿名页(如 mysqld 的堆内存)。 ❌ 不推荐(仍有风险) ⚠️
60(默认) 默认值,积极使用 swap → 绝对避免 ❌ 禁止用于 MySQL 生产服务器

🔍 关键澄清

  • swappiness=0 ≠ 禁用 swap,而是「仅当无可用内存 + 无可回收内存时才 swap」。
  • 不会阻止 swap 分区存在,但极大降低其被触发的概率。
  • 若你彻底不需要 swap(如内存充足且有监控告警),可 swapoff -a && 注释 /etc/fstab 中 swap 行,但 swappiness=0 已足够安全。

🛠️ 三、操作步骤(永久生效)

1. 临时设置(立即生效,重启失效)

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

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

# 或设为 1(兼容性更强)
sudo sysctl vm.swappiness=1

2. 永久设置(写入配置文件)

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

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

# 重载配置
sudo sysctl --system

3. (可选)禁用 swap 分区(仅当确认无需兜底)

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

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

验证是否生效

cat /proc/sys/vm/swappiness  # 应输出 0  
free -h                     # Swap 行应显示 total=0 或接近 0(若已 swapoff)

📊 四、配套最佳实践(同等重要!)

项目 建议
内存分配 innodb_buffer_pool_size 设置为 物理内存的 50%~75%(确保 OS 和其他进程有足够内存),避免内存过载。
监控告警 监控 MemAvailable/proc/meminfo)、SwapUsedmysql.global_status.Innodb_buffer_pool_wait_free。内存不足时提前扩容或优化查询。
NUMA 注意 若为 NUMA 架构(多 CPU 插槽),启用 numactl --interleave=all mysqld 避免内存跨节点访问延迟。
透明大页(THP) 必须禁用echo never > /sys/kernel/mm/transparent_hugepage/enabled(THP 与 InnoDB 内存管理冲突,加剧延迟)。

✅ 总结:一句话答案

不必物理删除 swap 分区,但必须将 vm.swappiness 设为 0(或 1)以禁止内核主动 swap;同时确保 innodb_buffer_pool_size 合理,避免内存过载——这才是 MySQL 8.0 高性能、高稳定的核心内存策略。

如需进一步诊断(如检查是否发生 swap、分析内存压力),可提供 free -h, cat /proc/meminfo, vmstat 1 5 输出,我可帮你分析。