我们有一台 8GB 的服务器,运行着 mysql、4 个 java 应用程序和一个小型 postgres db。在运行一些 mysql 查询时,系统分页出现了一些问题,因此,为了查看发生了什么,我们运行了一些命令来查看内存的使用情况。现在的问题是,我们找不到谁在使用我们 8 GB 中的 4 GB。以下是我们拥有的数据:
[root@server1 ~]# free -mt
total used free shared buffers cached
Mem: 7983 7934 49 0 65 584
-/+ buffers/cache: 7284 699
Swap: 5951 1032 4919
Total: 13935 8966 4968
因此,缓冲区和缓存的使用似乎非常小,因此内存应该主要用于进程:
按 %MEM 排序的结果为(仅限 %MEM > 0.0 的进程)
top - 16:31:00 up 3 days, 16:26, 3 users, load average: 0.51, 0.53, 0.56
Tasks: 153 total, 1 running, 151 sleeping, 0 stopped, 1 zombie
Cpu(s): 9.9%us, 0.6%sy, 0.0%ni, 85.3%id, 4.1%wa, 0.0%hi, 0.2%si, 0.0%st
Mem: 8175264k total, 8126480k used, 48784k free, 70312k buffers
Swap: 6094840k total, 1057440k used, 5037400k free, 595348k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ DATA nFLT nDRT COMMAND
7377 mysql 15 0 2677m 1.8g 4624 S 3.0 22.7 107:28.89 2.6g 95k 0 /usr/libexec/mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --pid-file=/var/run/mysqld/my
17836 root 21 0 2472m 1.0g 9872 S 2.3 13.2 11:18.44 2.4g 403 0 /usr/local/jdk1.6.0_25//bin/java -Djava.util.logging.config.file=/tomcat/conf/logging.properties -Drmi
17969 root 18 0 731m 222m 10m S 3.0 2.8 14:06.67 640m 33 0 /java//bin/java -Xms256m -Xmx256m -Xloggc:/var/log/gestorDeTramas.gc -XX:+PrintGCDetails -Dservice.mod
17980 root 21 0 407m 77m 10m S 0.0 1.0 0:04.35 313m 36 0 /java//bin/java -Xms32m -Xmx64m -Xloggc:/var/log/mensajero.gc -XX:+PrintGCDetails -Dservice.mode=rmi -
19866 postgres 15 0 160m 43m 34m S 11.3 0.5 1:51.57 9856 4 0 postgres: postgres mapas 127.0.0.1(46751) idle
24892 postgres 15 0 160m 41m 32m S 0.0 0.5 1:09.97 9804 3 0 postgres: postgres mapas 127.0.0.1(36534) idle
24891 postgres 15 0 160m 40m 31m S 0.0 0.5 0:50.74 9892 1 0 postgres: postgres mapas 127.0.0.1(36533) idle
24886 postgres 15 0 160m 40m 31m S 4.7 0.5 0:51.35 9936 0 0 postgres: postgres mapas 127.0.0.1(36528) idle
23622 postgres 15 0 160m 40m 31m S 0.0 0.5 0:55.42 9952 1 0 postgres: postgres mapas 127.0.0.1(47826) idle
24887 postgres 15 0 160m 40m 31m S 0.0 0.5 0:44.11 9888 2 0 postgres: postgres mapas 127.0.0.1(36529) idle
24880 postgres 16 0 160m 38m 29m S 4.3 0.5 0:42.49 9920 2 0 postgres: postgres mapas 127.0.0.1(36522) idle
24881 postgres 15 0 160m 29m 20m S 12.6 0.4 0:04.66 9948 0 0 postgres: postgres mapas 127.0.0.1(36523) idle
4139 root 34 19 256m 11m 1652 S 0.0 0.1 0:11.58 18m 902 0 /usr/bin/python -tt /usr/sbin/yum-updatesd
所以如果我添加 RES 列,我会得到大约 3.5GB。 那么,问题是,谁在使用我的物理内存?如果我添加 RES + 缓冲区 + 缓存,则大约有 4GB,而服务器有 8GB!我们可以做些什么来诊断服务器并查看谁在使用丢失的内存?
编辑:该服务器是 VMware 客户机。
还要注意,mysql 进程有很多页面错误。
更多数据:
[root@server1 ~]# cat /proc/meminfo
MemTotal: 8175264 kB
MemFree: 47204 kB
Buffers: 63180 kB
Cached: 611144 kB
SwapCached: 513392 kB
Active: 3458724 kB
Inactive: 538952 kB
HighTotal: 0 kB
HighFree: 0 kB
LowTotal: 8175264 kB
LowFree: 47204 kB
SwapTotal: 6094840 kB
SwapFree: 5037416 kB
Dirty: 342108 kB
Writeback: 44 kB
AnonPages: 3303684 kB
Mapped: 61352 kB
Slab: 79452 kB
PageTables: 19236 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
CommitLimit: 10182472 kB
Committed_AS: 5778312 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 266052 kB
VmallocChunk: 34359471959 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
Hugepagesize: 2048 kB
查看两个顶级进程使用了多少常驻内存的另一种方法是:
[root@server1 ~]# cat /proc/7377/smaps | grep ^Rss | awk '{A+=$2} END{print A}'
1852112
[root@server1 ~]#
[root@server1 ~]# cat /proc/17836/smaps | grep ^Rss | awk '{A+=$2} END{print A}'
1081620
答案1
系统是否为 vmware 客户机?如果是,VMware Balloon 驱动程序可以使用一些未说明的内存。
答案2
感谢 Minto Joseph 的回答,我发现 VMware 气球驱动程序(vmmemctl)正在使用丢失的内存。
cat /proc/vmmemctl
target: 1000894 pages
current: 1000894 pages
rateNoSleepAlloc: 16384 pages/sec
rateSleepAlloc: 2048 pages/sec
rateFree: 16384 pages/sec
timer: 325664
start: 3 ( 0 failed)
guestType: 3 ( 0 failed)
lock: 3623088 ( 29 failed)
unlock: 623698 ( 0 failed)
target: 325664 ( 2 failed)
primNoSleepAlloc: 3620199 ( 11 failed)
primCanSleepAlloc: 2900 ( 0 failed)
primFree: 2622165
errAlloc: 28
errFree: 28
getconf PAGESIZE
4096
所以你有 4GB
遗憾的是,vmmemctl 没有使用标准方法来报告它使用了多少内存,但我认为这是因为它的实现方式。
这主要参考自 vmware提供了大量有关内存膨胀的详细信息。我引用它,因为它与我们最初的问题(“如果服务器有未使用的内存,它为什么要进行分页?”)相关:
“通常,虚拟机管理程序在内存压力下会膨胀虚拟机气球。通过膨胀气球,虚拟机在主机上消耗的物理内存更少,但在客户机内部消耗的物理内存更多。因此,虚拟机管理程序将其部分内存过载卸载到客户机操作系统,同时稍微加载虚拟机。也就是说,虚拟机管理程序将内存压力从主机转移到虚拟机。膨胀会引起客户机内存压力。作为响应,气球驱动程序分配并固定客户机物理内存。客户机操作系统确定是否需要分页客户机物理内存以满足气球驱动程序的分配请求。如果虚拟机有足够的空闲客户机物理内存,则膨胀气球将不会引起分页,也不会影响客户机性能。在这种情况下,如图 6 所示,气球驱动程序从客户机空闲列表中分配空闲的客户机物理内存。因此,客户机级分页不是必需的。
但是,如果客户机已经面临内存压力,则客户机操作系统将决定将哪些客户机物理页面调出到虚拟交换设备,以满足气球驱动程序的分配请求。气球的妙处在于,它允许客户机操作系统智能地做出将哪些页面调出的艰难决定,而无需虚拟机管理程序的参与。”
“热气球天才”:)