速卖通素材
奋斗

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

服务器

在运行 MySQL 8.0 的生产环境中,通常建议关闭或极度降低 Swap 的使用,但“必须”一词取决于你的具体内存配置和负载场景。以下是详细的分析、设置方法以及最佳实践建议。

1. 核心结论:Swap 是否必须关闭?

结论:强烈建议禁用 Swap,或者将其 swappiness 值设置为极低(如 1)。

  • 为什么不建议使用 Swap?

    • I/O 瓶颈:MySQL 是数据库系统,对磁盘 I/O 延迟极其敏感。Swap 通常位于机械硬盘或速度较慢的 SSD 上,其读写速度远低于物理内存。一旦触发 Swap(即发生 "Thrashing"),数据库查询延迟会瞬间飙升,导致服务超时甚至不可用。
    • 性能抖动:即使只是偶尔发生 Swap 交换,也会造成严重的性能抖动,影响用户体验。
    • 数据一致性风险:在极端情况下,如果系统因内存不足而频繁交换,可能导致进程被 OOM Killer 终止,造成数据不一致或服务中断。
  • 什么时候可以保留少量 Swap?

    • 如果你的物理内存非常紧张,且业务允许偶尔的性能下降作为“保命符”,可以保留 Swap 以防止系统直接崩溃(OOM Kill)。但在生产环境中,这通常被视为架构设计缺陷(内存规划不足),而非依赖 Swap 来优化性能。

2. 如何设置 vm.swappiness

vm.swappiness 控制内核将匿名页(Anonymous Pages,主要是进程内存)换出到 Swap 的倾向性。取值范围是 0-100。

  • 默认值:通常为 60。这意味着系统比较积极地使用 Swap。
  • 推荐值
    • 生产环境(推荐)10
      • 1:仅当物理内存几乎耗尽时才使用 Swap,尽量避免。
      • 0:完全禁止将匿名页换出到 Swap(除非物理内存彻底耗尽,系统才会被迫使用)。
    • 开发/测试环境:可保持默认或设为 10,以便观察内存压力。

临时生效(重启后失效)

适用于快速测试或临时调整:

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

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

# 或者设置为 0 (激进)
sudo sysctl vm.swappiness=0

永久生效(推荐)

修改配置文件,确保重启后依然有效。

  1. 编辑 /etc/sysctl.conf 文件:
    sudo vi /etc/sysctl.conf
  2. 在文件末尾添加或修改以下行:
    vm.swappiness = 1
  3. 使配置立即生效:
    sudo sysctl -p

3. 进阶建议:彻底禁用 Swap

如果你确定物理内存充足(例如 MySQL 的 innodb_buffer_pool_size + 操作系统开销 < 总内存的 70%-80%),最安全的做法是直接关闭 Swap

临时关闭

sudo swapoff -a

永久关闭

  1. 编辑 /etc/fstab 文件:
    sudo vi /etc/fstab
  2. 找到包含 swap 的行(通常以 UUID 开头,类型为 swap),在其前面加上 # 进行注释。
    • 例如:UUID=xxxx-xxxx ... swap sw defaults 0 0 改为 # UUID=xxxx-xxxx ... swap sw defaults 0 0
  3. 保存退出并执行 sudo swapoff -a 立即生效。

注意:如果你使用了云厂商提供的实例,某些云平台可能强制要求开启 Swap 用于监控或特定功能,请先确认云厂商的最佳实践文档。


4. 关键配套:MySQL 内存配置 (my.cnf)

仅仅调整 Linux 内核参数是不够的,必须确保 MySQL 自身配置的内存不超过物理可用内存,否则内核会强制触发 Swap。

/etc/my.cnf/etc/mysql/my.cnf 中检查以下参数:

[mysqld]
# 核心参数:InnoDB 缓冲池大小
# 建议设置为物理内存的 50% - 70%(视操作系统和其他应用占用而定)
innodb_buffer_pool_size = 8G 

# 其他重要参数
innodb_log_file_size = 2G
max_connections = 200

计算公式参考:
$$ text{最大可用内存} = text{物理总内存} – (text{OS 预留} + text{其他应用}) $$
$$ text{innodb_buffer_pool_size} le text{最大可用内存} times 0.9 $$

如果 innodb_buffer_pool_size 设置过大,MySQL 启动时会尝试申请大量内存,导致系统剩余内存不足以维持 OS 正常运行,进而触发 Swap 或 OOM Killer。

总结 Checklist

  1. 评估内存:确保 innodb_buffer_pool_size 不会吃光所有物理内存。
  2. 调整 Swappiness:将 vm.swappiness 设置为 1
  3. (可选但推荐):如果内存规划合理,直接关闭 Swap (swapoff -a 并注释 fstab)。
  4. 监控:上线后使用 free -hvmstat 1 监控是否有 Swap 活动(si/so 列不为 0)。如果有,说明内存配置过小,需要增加内存或调小 MySQL 配置。
未经允许不得转载:轻量云Cloud » 运行 MySQL 8.0 的服务器,swap 分区是否必须关闭?如何设置 vm.swappiness?