VM.SWAPPINESS=0在最新内核中可能会OOM,MYSQL被意外KILL

在RHEL/CentOS6.4及更新版本内核中,vm.swappiness=0的行为已修改。此设置可能导致系统内存溢出并意外杀掉MySQL进程。文章详细解释了这一变化及其原因,并提供了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文:http://www.woqutech.com/?p=1397

请使用RHEL/CentOS 6.4及更新版本内核的MySQL同志们注意,vm.swappiness = 0的默认行为修改了,如果继续设置vm.swappiness = 0,有可能导致系统内存溢出,从而导致MySQL被意外kill掉。

 

在之前的《LINUX上MYSQL优化三板斧》中,我们建议大家把 vm.swappiness = 0 设置好。来尽量避免MySQL的服务器内存被交换出去。这样Linux在把内存交换出去时更偏向于将cache页交换出去,而不是将inactive页交换出去。详细描述请参考:http://www.woqutech.com/?p=1200

 

经常有人会问, vm.swappiness = 0会不会导致Linux在有swap空间的时候也不交换出去,从而导致内存溢出(OOM)。参照《LINUX上MYSQL优化三板斧》介绍,我们知道,这个值只是一个Linux在判断是否交换内存(swap)的一个“倾向”参考值,而并不是说,设置为0以后,Linux就完全不会使用内存交换空间。

 

但是,在较新的内核中(2.6.32-303.el6及以后),vm.swappiness = 0 的默认行为修改掉了,这个说法不再成立。设置该参数vm.swappiess=0,有可能导致MySQL数据库所在的系统出现内存溢出。一般来说,MySQL数据库占用的内存是整个服务器中最大的,根据Linux的策略,它会会首先把MySQL给Kill掉(调整 /proc/(pidof -s mysqld)/oom_adj可以改变OOM时kill的优先级),从而导致应用故障等。

 

这个修改是在内核3.5-rc1中提交的,并且合并到了2.6.32-303.el6及之后的各个版本。先让我们来看看这个patch:

http://gitorious.ti.com/ti-linux-kernel/ti-linux-kernel/commit/fe35004fbf9eaf67482b074a2e032abb9c89b1dd?format=patch

 

From fe35004fbf9eaf67482b074a2e032abb9c89b1dd Mon Sep 17 00:00:00 2001

From: Satoru Moriya <satoru.moriya@hds.com>

Date: Tue, 29 May 2012 15:06:47 -0700

Subject: [PATCH] mm: avoid swapping out with swappiness==0

 

Sometimes we'd like to avoid swapping out anonymous memory.  In

particular, avoid swapping out pages of important process or process

groups while there is a reasonable amount of pagecache on RAM so that we

can satisfy our customers' requirements.

 

OTOH, we can control how aggressive the kernel will swap memory pages with

/proc/sys/vm/swappiness for global and

/sys/fs/cgroup/memory/memory.swappiness for each memcg.

 

But with current reclaim implementation, the kernel may swap out even if

we set swappiness=0 and there is pagecache in RAM.

 

This patch changes the behavior with swappiness==0.  If we set

swappiness==0, the kernel does not swap out completely (for global reclaim

until the amount of free pages and filebacked pages in a zone has been

reduced to something very very small (nr_free + nr_filebacked < high

watermark)).

 

Signed-off-by: Satoru Moriya <satoru.moriya@hds.com>

Acked-by: Minchan Kim <minchan@kernel.org>

Reviewed-by: Rik van Riel <riel@redhat.com>

Acked-by: Jerome Marchand <jmarchan@redhat.com>

Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

---

 mm/vmscan.c |    6 +++---

 1 files changed, 3 insertions(+), 3 deletions(-)

 

diff --git a/mm/vmscan.c b/mm/vmscan.c

index 67a4fd4..ee97530 100644

--- a/mm/vmscan.c

+++ b/mm/vmscan.c

@@ -1761,10 +1761,10 @@ static void get_scan_count(struct mem_cgroup_zone *mz, struct scan_control *sc,

   * proportional to the fraction of recently scanned pages on

   * each list that were recently referenced and in active use.

   */

-   ap = (anon_prio + 1) * (reclaim_stat->recent_scanned[0] + 1);

+   ap = anon_prio * (reclaim_stat->recent_scanned[0] + 1);

   ap /= reclaim_stat->recent_rotated[0] + 1;

 

-   fp = (file_prio + 1) * (reclaim_stat->recent_scanned[1] + 1);

+   fp = file_prio * (reclaim_stat->recent_scanned[1] + 1);

   fp /= reclaim_stat->recent_rotated[1] + 1;

   spin_unlock_irq(&mz->zone->lru_lock);

 

@@ -1777,7 +1777,7 @@ out:

      unsigned long scan;

 

      scan = zone_nr_lru_pages(mz, lru);

-      if (priority || noswap) {

+      if (priority || noswap || !vmscan_swappiness(mz, sc)) {

          scan >>= priority;

          if (!scan && force_scan)

             scan = SWAP_CLUSTER_MAX;

-- 

1.7.5

 

就像Satoru Moriya所说的那样,在之前的版本中,就算我们设置了swappiness=0并且RAM中还有pagecache,内核也可能会交换出部分匿名内存页。而为了“满足用户的需求”,这个patch修改了swappiness=0的行为,如果你设置swappiness=0,那么只有在(nr_free + nr_filebacked < high watermark)才会交换内存,也就是说空闲内存和文件缓存基本没有了才会触发内存swap。这样的话,副作用在于:内存如果不够了,Linux有可能触发OOM,从而kill掉耗费内存最多的MySQL进程。

 

在2.6.32-303.el6 RHEL/CentOS及更新版本的内核中,该patch就已经被合并进来:

* Mon Aug 27 2012 Jarod Wilson <jarod@redhat.com> [2.6.32-303.el6]

...

- [mm] avoid swapping out with swappiness==0 (Satoru Moriya) [787885]

其他分发版本的Linux(比如Debian,Ubuntu)的版本中,请各位自己查阅一下,看看时候已经合并该patch。

RHEL/CentOS 6.3的内核版本是2.6.32-279,而RHEL/CentOS 6.4的内核为2.6.32-358,从这个版本开始,swappiness的行为就已经修改了,使用这个版本及之后版本的同志们需要特别注意一下。

 

解决的办法其实也很简单,

1、尽量保证Linux操作系统还有足够的内存

2、最新的内核,建议把vm.swappiness设置1

3、考虑设置 /proc/(pidof -s mysqld)/oom_adj为较小的值来尽量避免MySQL由于内存不足而被关闭。

 

参考:

https://github.com/torvalds/linux/blob/master/mm/vmscan.c

http://gitorious.ti.com/ti-linux-kernel/ti-linux-kernel/commit/fe35004fbf9eaf67482b074a2e032abb9c89b1dd?format=patch

http://www.mysqlperformanceblog.com/2014/04/28/oom-relation-vm-swappiness0-new-kernel/

<think>嗯,用户问的是如何判断服务器内存不足。我需要先理解用户的需求。可能用户是系统管理员,或者是开发人员,遇到了服务器性能问题,想排查是不是内存不够用。他们可能已经注意到服务器变慢、应用崩溃,或者监控系统发出警报,想确认是否是内存问题。 首先,我得回忆一下常见的检查内存的方法。通常,在Linux系统里,可以用free命令查看内存使用情况,或者top、htop这些工具。Windows的话,任务管理器或者性能监视器。不过用户可能更熟悉Linux,因为服务器常用。 然后要考虑内存不足的表现。比如,free命令中available很少,swap使用率高,或者出现OOM Killer的日志。这些都是关键点。另外,缓存(cache)和缓冲(buffer)的区别也需要解释清楚,因为有时候用户看到used很高,但其实是缓存,实际可用内存可能还够。 还要想到其他可能的问题,比如内存泄漏,或者某个进程占用过多内存。这时候需要检查进程的内存使用情况,比如用ps或者top排序。另外,监控工具如Prometheus、Zabbix的设置,可能用户想长期监控,所以得提到设置警报阈值。 用户可能不太清楚如何具体操作,比如查看OOM日志的位置,或者如何配置监控。这时候需要给出具体的命令,比如grep -i oom /var/log/syslog,或者解释vmstat的输出含义。还要注意解释术语,比如swapiness,避免用户混淆。 另外,用户可能想知道临时解决方案和长期解决方案。比如临时释放内存的方法,如清理缓存,或者终止进程。长期的话,增加内存、优化应用代码、调整配置等。需要分点说明,结构清晰。 可能存在的误区是,用户看到内存使用率高就以为不足,但实际上Linux会利用空闲内存做缓存,这部分是可释放的。所以需要强调available字段的重要性,而不仅仅是used。这也是常见的混淆点,需要特别指出。 最后,确保回答覆盖了不同操作系统,比如Linux和Windows,但主要侧重Linux,因为服务器环境。同时,给出实际案例,比如当available接近零,swap使用增加,这时候可能内存不足,帮助用户理解判断依据。 总结下来,回答的结构应该是先介绍检查方法,包括命令和工具,再说明判断指标,然后给出解决方案,最后补充注意事项或案例。这样用户能一步步排查,确认问题并采取相应措施。</think>判断服务器内存是否不足,可以通过以下方法和指标进行排查和分析: --- ### **一、检查内存使用情况** #### **1. 使用命令行工具(Linux系统)** - **`free -h` 命令** 查看内存总量、已用内存、空闲内存、缓存(Cache)和缓冲(Buffer)等信息。 **关键指标**: - `available`:系统可用内存(包括未被使用的内存和可回收的缓存)。 - 如果 `available` 接近 0,且 `free` 内存极少,可能内存不足。 - **`top` 或 `htop` 命令** 实时监控内存使用情况,按内存占用排序(在 `top` 界面按 `Shift+M`)。 **关注列**: - `%MEM`:进程占用物理内存的百分比。 - `VIRT`:进程使用的虚拟内存总量。 - **`vmstat 1` 命令** 查看内存、交换分区(swap)、I/O 等动态信息。 **关键指标**: - `si`(swap-in):每秒从磁盘读入内存的数据量(单位 KB)。 - `so`(swap-out):每秒从内存写入磁盘的数据量。 若 `si`/`so` 持续较高,说明物理内存不足,系统频繁使用交换分区。 --- #### **2. 监控工具(通用)** - **图形化工具**:如 `nmon`(Linux)、任务管理器(Windows)、`glances` 等。 - **专业监控系统**:Zabbix、Prometheus + Grafana、Nagios 等,可设置内存阈值告警(如使用率超过 90%)。 --- ### **二、内存不足的典型表现** 1. **系统响应变慢** - 应用程序卡顿,SSH 登录延迟高。 - 频繁触发交换分区(swap),导致磁盘 I/O 增加(机械硬盘尤其明显)。 2. **频繁触发 OOM Killer** - Linux 内核在内存耗尽时会强制终止占用内存大的进程(日志路径:`/var/log/messages` 或 `dmesg`)。 - 通过 `grep -i 'oom' /var/log/syslog` 搜索 OOM 记录。 3. **内存使用率持续高位** - 物理内存使用率(`used/(total)`) 长期超过 90%,且 `available` 内存极低。 4. **服务异常崩溃** - 数据库(如 MySQL)、Java 应用等因申请不到内存而崩溃,日志中可能报错 `Cannot allocate memory`。 --- ### **三、排查与解决方案** #### **1. 临时缓解** - **释放缓存**(Linux): ```bash echo 1 > /proc/sys/vm/drop_caches # 释放页面缓存(谨慎操作) ``` - **终止异常进程**:通过 `kill` 或 `systemctl` 结束占用内存过高的进程。 - **增加 swap 空间**(仅临时应急,性能差)。 #### **2. 长期优化** - **升级硬件**:增加物理内存。 - **优化应用程序**:减少内存泄漏,调整 JVM 堆大小(Java 应用),优化查询(数据库)。 - **调整系统参数**: - 修改 `vm.swappiness`(降低 swap 使用倾向,默认值 60)。 - 限制进程内存(如通过 `cgroup`)。 #### **3. 监控与告警** - 设置内存使用率、swap 使用量的监控告警(如阈值超过 80% 触发通知)。 --- ### **四、注意事项** - **区分缓存(Cache)和实际占用**:Linux 会利用空闲内存缓存磁盘数据,这部分内存可快速释放,因此 `available` 比 `free` 更关键。 - **结合其他指标**:内存不足可能导致 CPU I/O 等待(`wa`%)升高,需综合判断。 --- 通过以上方法,可以快速定位内存问题并采取相应措施。如果内存不足是常态,建议优先优化程序或扩容硬件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值