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

在运行 MySQL 8.0(尤其是生产环境)的 Linux 服务器上,swap 分区不必须物理删除或禁用,但强烈建议关闭 swap 或将其影响降至最低,核心目标是避免 MySQL 进程被交换到磁盘(swap out),从而引发严重性能退化甚至服务不可用

以下是专业、可落地的建议和配置说明:


✅ 一、为什么 MySQL 对 swap 敏感?

  • MySQL 是内存密集型服务,依赖 Buffer Pool、InnoDB Log Buffer、Sort Buffer 等大量常驻内存结构。
  • 若内核因内存压力将 MySQL 的匿名页(如 Buffer Pool 页面)swap 到磁盘:
    • 一次 SELECT 可能触发 毫秒级 → 秒级延迟(磁盘 I/O vs 内存访问);
    • InnoDB 崩溃恢复、DDL 操作、大事务可能卡死;
    • SHOW PROCESSLIST 中大量线程处于 Sending data/Copying to tmp table 等状态却无进展;
    • vmstat 1 观察到持续 si(swap-in)和 so(swap-out)非零值,即危险信号。

💡 注意:MySQL 本身不会主动使用 swap(除非 OOM Killer 触发或配置不当),但内核会根据 swappiness 和内存压力决定是否 swap 进程页。


✅ 二、vm.swappiness 推荐设置

场景 推荐值 说明
生产 MySQL 服务器(推荐) 1 ⭐ 最佳实践。几乎禁止 swap,仅在极端内存耗尽(OOM 前)才 swap 少量非关键页,极大降低 MySQL 被 swap 风险。
严格禁止 swap(可选) 0 内核 仅在内存真正不足时才 swap(Linux 4.12+ 行为:swappiness=0 表示“尽可能不 swap”,但仍可能 swap 匿名页;而 vm.mmap_min_addr=0 + sysctl -w vm.swappiness=0 并不能完全阻止)。
⚠️ 注意:swappiness=0 不等于禁用 swap,swap 分区仍存在,OOM Killer 仍可能 kill 进程。
❌ 不推荐 60(默认)或 >10 默认值极易导致 MySQL 内存被 swap,尤其当系统有其他进程(如监控、日志、备份脚本)竞争内存时。

生产环境强烈推荐:vm.swappiness = 1


✅ 三、完整配置步骤(永久生效)

1. 临时生效(立即应用)

sudo sysctl -w vm.swappiness=1

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

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. (可选)验证当前值

cat /proc/sys/vm/swappiness
# 或
sysctl vm.swappiness

✅ 四、进阶建议:配合其他调优项

项目 推荐配置 说明
禁用 transparent huge pages (THP) echo never > /sys/kernel/mm/transparent_hugepage/enabled MySQL(尤其 InnoDB)与 THP 兼容性差,易导致延迟抖动。需开机自启(通过 /etc/rc.local 或 systemd service)。
预留内存给 OS & 其他进程 MySQL innodb_buffer_pool_size ≤ 75–80% of total RAM(非 NUMA 系统) 避免 MySQL 吃光内存导致内核频繁回收/swap。例如 64GB 内存 → 设为 48G
启用 oom_score_adj 保护 MySQL echo -1000 > /proc/$(pgrep -f "mysqld")/oom_score_adj 降低 OOM Killer 杀 MySQL 进程的概率(需配合 systemd 服务配置持久化)。
监控 swap 使用 sar -W 1 10(每秒查看 swap in/out)
free -hswapon --show
持续监控,若 so > 0 频繁出现,说明内存严重不足或配置不合理。

❌ 五、常见误区澄清

误区 澄清
“只要关掉 swap 分区就绝对安全” 错!swap 分区禁用后,若内存不足,OOM Killer 会直接 kill 进程(MySQL 可能被杀),反而更不可控。保留 swap + swappiness=1 是更平滑的防御策略。
“MySQL 用了 malloc() 就不会被 swap” 错!malloc 分配的是虚拟内存,其物理页仍受 swappiness 影响。InnoDB Buffer Pool 使用 mmap(MAP_ANONYMOUS),正是内核 swap 的主要目标。
“云服务器(如 AWS EC2)不需要调优” 错!云实例同样存在 swap 风险(尤其通用型实例),且云盘 I/O 延迟更高,swap 后性能雪崩更严重。

✅ 总结:生产 MySQL 8.0 的内存策略

项目 推荐操作
swap 分区 ✅ 保留(不格式化/不 swapoff -a),但设为极低优先级(swappiness=1
vm.swappiness 永久设为 1(非 0,非 60
内存分配 innodb_buffer_pool_size ≤ 75–80% RAM,预留足够给 OS、连接线程、tmp table 等
其他关键项 ✅ 关闭 THP、监控 swap I/O、设置 oom_score_adj、定期 free -h + vmstat 1 巡检

🔚 最终口诀
“Swap 不删,swappiness 设 1;内存留足,THP 关闭;宁让 OOM Kill,不许 Swap 拖垮。”

如需我帮你生成对应系统的 systemd 服务配置(如自动设置 swappiness/THP)、或检查当前 MySQL 内存配置合理性,请提供你的 cat /proc/meminfomysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; 输出,我可以进一步诊断 👇

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