swappiness是RHEL系统内存调优中出现频率最高的参数之一,但也是被误解最多的一个。有人把它当成swap开关,有人认为设成0性能最好,结果数据库服务器上OOM killer频繁杀进程才追悔莫及。这篇文章从内核回收机制出发,把swappiness的真正含义讲清楚,再针对不同业务场景给出具体的调优建议和操作步骤。

一、swappiness到底控制什么:从内核回收机制说起
很多人对swappiness的理解停留在字面意思上,认为它就是“使用swap的积极程度”,这个理解不够准确,容易导致错误配置。要真正弄懂它,需要先了解Linux内核在内存压力下是如何回收页面的。
当系统可用内存不足时,kswapd内核线程会被唤醒,开始回收内存。回收的对象主要分两类:一类是文件页(file-backed pages),比如程序代码、文件缓存,这类页面可以直接丢弃或者回写磁盘;另一类是匿名页(anonymous pages),比如堆内存、进程栈,这类页面没有对应的磁盘文件,回收它们只能写入swap分区。swappiness的本质,就是告诉内核在这两类页面之间做权衡时,倾向于回收哪一类。
具体到数值,swappiness取值范围是0到100。在内核较老的版本里,它是一个权重比例的概念:60意味着匿名页与文件页的回收比例大致相当。在RHEL 7及以后的3.10+内核中,这个计算公式经过了几次调整,2018年之后的内核(比如RHEL 8的4.18内核)里,swappiness=0的含义已经变为:仅当文件页回收无法满足需求、即将触发OOM时,才允许回收匿名页。注意这并不等于禁用swap,而是把swap作为最后的救命手段。
可以做一个简单实验来感受差异。准备一台内存4GB、装有swap分区的RHEL虚拟机,执行下面的命令:
# 查看当前值 cat /proc/sys/vm/swappiness # 临时改为10 sysctl -w vm.swappiness=10 # 用stress-ng制造内存压力,观察swap使用情况 stress-ng --vm 2 --vm-bytes 2G --timeout 300s & # 观察si/so列,这是swap换入换出的速率 vmstat 1
把swappiness分别设为10和80重复实验,对比vmstat输出中si、so两列的数值变化,能直观感受到内核回收策略的差异。so列持续有数值说明页面正在被换出到swap,这个值长期不为零往往是性能问题的信号。
二、设为0就万事大吉?一个常见误区引发的事故
网上流传最广的说法是“性能敏感的服务器把swappiness设成0”,这个建议如果被机械执行,可能引发严重问题。这里需要区分内核版本:在RHEL 6时代的2.6.32内核中,swappiness=0确实意味着内核尽量避免使用swap,行为上接近禁用;但在2018年更新的内核中,如前面所说,0只代表“最后手段”,行为是相对安全的。真正危险的做法是另一个极端——直接把swap分区关掉。
有一类故障案例很典型:DBA在Oracle服务器上执行swapoff -a,理由是“swap根本不该被用到,留着浪费磁盘”。表面上一切正常,直到某个业务高峰期内存申请突增,内核没有swap这个缓冲池可以临时安置冷页面,只能直接触发OOM killer。被杀掉的往往是大内存的Oracle后台进程,数据库实例直接崩溃,恢复成本远超预期。swap在正常运行时不承载业务数据,它的价值在于给内核提供一个缓冲空间,让突然的内存尖峰有回旋余地。
另一个值得关注的点是默认值的选择。RHEL系统根据内存大小给出了不同的默认值:内存超过100GB的大机器,安装器会把swappiness自动设为1;小内存机器则保持60。这个设计说明红帽官方的态度很明确:大内存服务器应该极不倾向使用swap,但绝不建议完全堵死这条路。理解了这个设计思路,自己调优时就不会走极端。
| 系统情况 | 默认swappiness | 说明 |
|---|---|---|
| 内存大于100GB的RHEL安装 | 1 | 安装器自动降低 |
| 普通内存的RHEL安装 | 60 | 内核通用默认值 |
| swapoff -a后的系统 | 无意义 | swap被禁用,参数失效,风险极高 |
三、不同场景的推荐值与持久化配置实操
调优没有万能答案,swappiness的推荐值强依赖于业务负载类型。可以按照下面几类场景来对号入座。
第一类是数据库服务器,包括Oracle、MySQL、PostgreSQL等。数据库的SGA或buffer pool属于典型的大块匿名内存,一旦被换出到swap,下一次访问就要付出磁盘IO的代价,性能会断崖式下跌。这类服务器推荐设为1到10之间,红帽官方文档对Oracle RAC的建议值就是1。同时务必保持监控,如果发现数据库进程的swap占用持续增长,说明内存规划本身有问题,应该扩内存而不是调参数。
第二类是虚拟化宿主机,也就是KVM、VMware ESXi上跑大量虚拟机的物理机。KSM(内核同页合并)和气球驱动会让内存行为更复杂,宿主机上的swap换出可能连带影响多台虚拟机。这类机器推荐设为10左右,同时为每台虚拟机的QEMU进程保留一定的swap余量,防止内存超分时直接OOM杀掉虚拟机进程。
第三类是普通的Web应用、中间件服务器。这类负载文件页占比较高,页面缓存对性能影响明显,默认的60其实不算差。如果没有观察到明显的swap换入换出,完全没有必要动这个参数。性能优化的一条基本原则:先测量,再动手。用sar -B和vmstat确认存在swap thrashing现象之后,再考虑调低,一般调到10到30之间即可。
确定数值之后,修改分临时和持久两步。临时修改用sysctl -w,重启后失效,适合验证效果:
# 临时修改,立即生效 sysctl -w vm.swappiness=10 # 验证 sysctl vm.swappiness
确认效果符合预期后,做持久化配置。推荐使用/etc/sysctl.d目录下的独立文件,而不是直接改/etc/sysctl.conf,这样便于多参数分组管理:
# 创建独立配置文件 cat > /etc/sysctl.d/99-swappiness.conf << 'EOF' vm.swappiness = 10 EOF # 重新加载所有sysctl配置 sysctl --system # 确认生效 cat /proc/sys/vm/swappiness
注意sysctl --system会按照目录顺序加载所有配置文件,如果机器上有云平台或安全基线下发的其他sysctl文件也设置了swappiness,后加载的会覆盖前面的。排查“为什么改了不生效”时,用sysctl --system的输出检查各文件的加载顺序,往往能找到原因。
四、调优之后如何验证:用数据说话
改完参数不等于调优结束,必须用监控数据验证效果。核心观察指标有四个:vmstat输出中的si和so列、sar -W报告的换页速率、/proc/meminfo中的SwapFree变化,以及smem工具统计的进程级swap占用。
# 每10秒采样一次换页情况,采集一整天 sar -W 10 8640 > /tmp/swapstat.log # 查看哪些进程占了swap,smem比top更准确 smem -r -k -s swap | head -20
理想的调优结果有两种。一种是si、so长期接近零,说明内核基本不再主动换出匿名页,内存压力主要靠回收文件页化解;另一种是业务低峰期so有小量数值、高峰期si有少量数值,这属于正常的冷页面安置,不必强求归零。真正要警惕的是si和so同时长期保持高位,这说明物理内存严重不足,调swappiness只是缓解症状,根治手段是加内存或者优化应用的内存占用。
还有一个容易被忽略的坑:NUMA架构的大内存机器上,某个NUMA节点内存耗尽可能引发频繁换页,即使整机还有空闲内存。这种情况调swappiness收效甚微,需要结合numastat输出检查各节点的内存分布,必要时在BIOS里关闭NUMA balancing或者调整应用的内存绑定策略。内存问题从来不是单一参数能包治百病的,swappiness只是工具箱里的一件工具,理解它的适用边界,比记住一个推荐值更重要。
swappinessRHEL性能调优Linux内存管理修改时间:2026-09-06 18:58:45