swappiness=1在生产数据库服务器上成标配,因默认值60会过早换出匿名页引发毫秒级卡顿;设为1仅OOM时启用swap,兼顾安全与性能。

为什么 swappiness=1 在生产数据库服务器上几乎成了标配
因为默认值 swappiness=60 会让内核在物理内存还有大量空闲时就急着把匿名页(如堆内存)换出到 swap,这对延迟敏感的数据库(PostgreSQL、MySQL)是灾难性的——一次 swapin 可能导致几百毫秒的卡顿。设为 1 并非禁用 swap,而是只在真正濒临 OOM 时才启用,既保留了安全垫,又避免了无谓抖动。
实操建议:
- 临时生效:
sudo sysctl vm.swappiness=1
- 永久生效:在
/etc/sysctl.conf中追加vm.swappiness=1,再运行sysctl -p - 注意:容器环境(如 Docker)中该参数需在宿主机设置,容器内修改无效
- 验证是否生效:
cat /proc/sys/vm/swappiness,不是看sysctl vm.swappiness的输出(可能缓存)
vm.vfs_cache_pressure 调高还是调低?看你的 workload 类型
这个参数控制内核回收 dentry 和 inode 缓存的积极程度。默认值 100 对通用场景合理,但对大量小文件读写的业务(如 Git 仓库服务、CI/CD 构建节点),缓存压力过大会频繁丢弃路径缓存,导致 open()、stat() 系统调用变慢。
实操建议:
- 小文件密集型服务:设为
50~80,保留更多 dentry/inode,减少路径查找开销 - 大文件流式处理(如日志归档、视频转码):可保持默认或略调高至
120,避免缓存长期霸占内存 - 不要设为
0:内核不会完全不回收,且会引发其他异常行为(如slabinfo统计失真) - 观察指标:
grep -i "dentry\|inode" /proc/meminfo,结合slabtop -o看dentry和inode_cache占比
为什么 echo 1 > /proc/sys/vm/drop_caches 在生产环境基本没用
这条命令只能释放 pagecache、dentries 和 inodes,但无法释放 slab 分配器管理的内核对象(如 socket buffers、ext4 inode)、用户态进程堆内存、或被 mlock() 锁住的页。真正吃掉内存的往往是 slab 或应用自身泄漏,清 cache 只是“擦黑板”,不解决根本问题。
实操建议:
- 别把它当“内存清理神器”——线上执行后
free -h显示可用内存上升,不代表系统更健康 - 若发现
Slab占用持续增长(cat /proc/meminfo | grep Slab),优先查slabtop -o找 top 消耗者,比如kmalloc-192或ext4_inode_cache - 确认是否真有内存压力:看
/proc/vmstat中的pgmajfault(缺页中断)、pgpgin/pgpgout(IO 换入换出量),比看free更可靠 - 自动触发
drop_caches的脚本在生产环境属于危险操作,应禁止
Redis / Elasticsearch 这类应用必须配 vm.overcommit_memory=1
这些应用启动时会预分配大量虚拟内存(如 Redis 的 maxmemory + 预留空间),但实际物理页按需分配。默认 overcommit_memory=0(启发式检查)会在进程 malloc() 超过系统剩余内存时直接失败,导致启动报 Cannot allocate memory,哪怕物理内存明明够用。
实操建议:
- 设为
1表示“永远允许 overcommit”,依赖 OOM killer 在真正爆内存时介入,这是最稳妥的选择 - 绝对不要设为
2并配vm.overcommit_ratio:该模式下内核按硬公式计算可用内存(Swap + RAM * ratio/100),极易误判,尤其在 swap 关闭时直接归零 - 配置后需重启对应服务才能生效(因为
malloc()行为在进程启动时确定) - 验证方式:
cat /proc/sys/vm/overcommit_memory,同时检查/proc/sys/vm/overcommit_ratio是否仍为默认50(设为 1 时该值无效)
内存调优不是调参比赛,每个改动都要对应到具体 workload 的行为特征。最常被忽略的是:没关掉 transparent hugepage(/sys/kernel/mm/transparent_hugepage/enabled),它在某些 OLTP 场景下反而增加锁竞争和内存碎片。










