发布时间:2026-09-17 12:31 更新时间:2026-09-17 12:31 阅读量:0
半夜收到监控告警:某台服务器 swap 使用率从 5% 一路涨到 70%。第一反应往往是「内存不够了,赶紧加内存」,但真到机器上一看,free -m 显示可用内存还有一大截,swap 却稳稳占着几个 GB 不释放。这时候加内存可能白花钱,真正的问题也许只是长期不活跃的匿名页被换出后一直没被换回来。要判断 swap 涨得是否健康,不能只看使用率这一个数字,得把「用了多少」和「换得有多频繁」分开看。
swap 使用率是个存量指标,表示有多少内存页被写到了交换分区,它只涨不跌是常态——只要这些页没有被再次访问,内核不会主动把它们搬回物理内存。所以一台跑了几周的机器,swap 占到 30%~50% 往往只是说明它把冷数据挪出去了,并不等于内存紧张。
真正反映压力的是换页速率,也就是 vmstat 里的 si(swap in)和 so(swap out)。如果这两个值长期贴着 0,只是 swap 占用高,那属于正常换页;如果 si/so 持续是几百上千 KB 甚至几 MB 每秒,同时伴随较高的等待,那才说明物理内存确实不够,系统在物理内存和磁盘之间来回倒腾。更严重的情况是内存回收跟不上分配速度,触发 OOM Killer 直接杀进程,这时 dmesg 里会有明确记录。
# 看内存与 swap 的存量
free -h
每 2 秒采样一次,重点看 si / so 两列(单位 KB/s)
vmstat 2 10
每秒换页次数,r 表示每秒换入,w 表示每秒换出
sar -W 1 5
vmstat 输出里还要顺带看 r(运行队列)和 b(阻塞进程数)。如果 r 不大、si/so 也接近 0,那 swap 高就只是个存量问题,不必紧张;反之若 b 很大、si/so 持续非零,说明进程在等内存或等磁盘 IO,才是需要处理的信号。
确认内存确有压力后,下一步是找出「元凶」。常见误区是只看 top 的 RES 列排名,但 RES 会把共享内存重复计算,容易误判。更可靠的做法是按进程的 RSS 排序,再结合 /proc 里的 smaps 看哪些页真的被换出到 swap。
# 按 RSS 从大到小列出前 15 个进程
ps -eo pid,comm,rss,vsz --sort=-rss | head -n 15
查看某个进程被换出的内存量(Swap 字段)
awk '/^Swap:/{s+=$2} END{print s" kB"}' /proc/<PID>/smaps
汇总全系统被换出的匿名页总量
grep -c . /proc/*/smaps 2>/dev/null | wc -l # 进程多时慎用,仅作粗查
直接看内核统计的换入换出总量
cat /proc/vmstat | grep -E 'pswpin|pswpout'
如果某个 Java 或数据库进程的 Swap 值有几百 MB,说明它的内存页被大量换出,运行时会频繁触发缺页中断,表现为响应变慢、GC 时间变长。这类进程通常需要设置内存上限并尽量避免被换出,而不是简单加内存了事。反过来,如果被换出的都是空闲的日志处理、后台任务,那影响就有限。
还要留意一种特殊情况:cgroup 的 memory.swap 限制、容器的 swap 配置、以及 NUMA 节点间的不均衡,都可能让某部分内存看起来「够用」而实际分配不到。具体口径以当前内核版本和实际环境为准,建议对照官方文档核对对应参数路径。
判断清楚之后处理思路就明确了。如果只是存量高、速率低,可以不动;如果速率持续高,优先考虑扩容内存或优化应用内存占用。在动手之前,可以先调整 vm.swappiness,它控制内核有多愿意把匿名页换出去,默认值通常是 60,数据库类机器常调到 1~10 以减少换出,但调得太低也可能导致内存回收不及时。
# 查看当前值
cat /proc/sys/vm/swappiness
临时调整为 10
sysctl -w vm.swappiness=10
永久生效,写入配置文件
echo 'vm.swappiness=10' >> /etc/sysctl.d/99-swap.conf
sysctl --system
如果确实需要临时缓解,可以用 swapoff/swapon 把 swap 内容拉回物理内存,但前提是物理内存真的够,否则会触发 OOM;操作前务必确认空闲内存大于 swap 占用量,并尽量在业务低峰执行。执行 swapoff -a 后再 swapon -a 即可恢复,整个过程会占用一定 IO,线上谨慎操作。
另外记得核对 swap 分区或 swap 文件的大小是否合理。传统建议是 swap 等于内存的 1~2 倍,但在内存普遍较大的今天,这个经验值需要按负载类型调整,数据库、缓存类服务更依赖物理内存,swap 只作为兜底。具体取值以实际业务压测结果为准,不要照搬固定比例。
最后小结一下判断顺序:先看 free 的存量,再用 vmstat 看 si/so 速率,然后用 ps 和 smaps 定位被换出的进程,最后决定是不处理、调 swappiness 还是扩容内存。swap 使用率高本身不是故障,只有换页速率持续非零、阻塞进程增多、响应变慢同时出现,才说明内存真的不够用。建议给 swap 使用率和 si/so 速率都配上监控告警,把「存量高」和「速率高」分成两条规则,这样才不会被一个数字牵着走。
| 📑 | 📅 |
|---|---|
| 系统盘满了却找不到大文件:被删除但仍被进程占用的句柄排查与恢复空间 | 2026-09-17 |
| MySQL表空间与ibdata1膨胀处理:独立表空间、碎片整理与磁盘回收 | 2026-09-17 |
| SSH 连接频繁断开与卡顿排查:心跳、MTU 与 DNS 反解 | 2026-09-17 |
| Linux内存被缓存吃满:buff/cache该不该手动释放 | 2026-09-17 |
| 服务器时间不同步导致证书与定时任务异常:NTP/chrony 校时配置与排查 | 2026-09-16 |
| Docker容器时区不对?TZ变量与localtime挂载的正确用法 | 2026-09-17 |
| journald 日志占满 /var/log:持久化与容量限制配置 | 2026-09-18 |
| Linux网卡丢包与TCP重传排查:ip -s link、ss -ti与ethtool实战 | 2026-09-18 |
| Nginx 静态资源 404 与权限被拒排查:root、alias、try_files 的坑 | 2026-09-18 |
| systemd-journald 日志转发远程 syslog:rsyslog 对接与丢日志排查 | 2026-09-19 |