在运行 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 -h、swapon --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/meminfo 和 mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; 输出,我可以进一步诊断 👇
云知识CLOUD