最近这些天有一台服务器总是会收到剩余swap过低的告警。
邮件内容大体如下:
############
ZABBIX-监控系统:
------------------------------------
报警内容: Lack of free swap space on ora_test_s2_yangjr@10.127.2.xxxx
------------------------------------
报警级别: PROBLEM
------------------------------------
监控项目: Free swap space in %:21.59 %
------------------------------------
报警时间:2015.11.23-04:10:57
简单查看了一下服务器配置,发现是一个32G的服务器,swap空间为8G,目前已经使用6G多。架构如图所示
top - 11:56:03 up 152 days, 2:06, 1 user, load average: 0.53, 0.34, 0.27
Tasks: 338 total, 1 running, 326 sleeping, 0 stopped, 11 zombie
Cpu(s): 5.6%us, 0.0%sy, 0.0%ni, 94.4%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 32949076k total, 32846716k used, 102360k free, 237324k buffers
Swap: 8385920k total, 6427096k used, 1958824k free, 28360876k cached
对于这个,简单分析了一下,原来这台服务器上再运行两个数据库实例
oracle 5606 1 0 Jun24 ? 00:01:12 ora_smon_ctest
oracle 10533 1 0 Jun27 ? 00:01:11 ora_smon_catest
oracle 21950 21560 0 17:54 pts/0 00:00:00 grep smon
从smon初始化的时间来看,这两个数据库实例大概是在7月底启动的,时间有一些先后。
这两个库是11g的DG环境。所以平时主要是会有归档的接收和应用。
为什么会发生swap争用呢,首先想到的就是内存组件的设置问题,是不是设置过大,导致没有富裕的内存资源可用了。
查看数据库实例ctest
SQL> show parameter sga
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
lock_sga boolean FALSE
pre_page_sga boolean FALSE
sga_max_size big integer 12032M
sga_target big integer 12032M
SQL> show parameter pga
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_target big integer 4010M
所以对于ctest sga+pga=12G+4G=16G,大体如此。
对于数据库实例catest,内存组件大小为;
SQL> show parameter sg
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
lock_sga boolean FALSE
pre_page_sga boolean FALSE
sga_max_size big integer 20G
sga_target big integer 20G
SQL> show parameter pga
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_target big integer 8530M
所以简单相加就是20G+8G=28G
如此一来,28G+16G=44G,而内存资源只有32G,那剩下的12G是怎么来的。如果排除法,也就只有swap了。
当然数据库层面没有任何的异常,也没有限制sga无法设置成功之类的问题。听起来倒也相安无事。
查看v$dynamic_components得到的信息如下:
catest的内存组件大小为:2G+18G=20G
$sh showbuffer.sh
[oracle@scycard2 dbm_lite]$ sh showbuffer.sh
COMPONENT CURRENT_M MIN_M MAX_M SPECCIFIED_M LAST_OPER LAST_OPER_TYP GRANULE_M
------------------------------ ---------- ---------- ---------- ------------ --------- ------------- ----------
shared pool 2304 2304 2304 0 STATIC 64
large pool 64 64 64 0 STATIC 64
java pool 64 64 64 0 STATIC 64
streams pool 0 0 0 0 STATIC 64
DEFAULT buffer cache 17920 17920 17920 15360 INITIALIZING 64
ctest的内存组件大小为:
$ sh showbuffer.sh
COMPONENT CURRENT_M MIN_M MAX_M SPECCIFIED_M LAST_OPER LAST_OPER_TYP GRANULE_M
------------------------------ ---------- ---------- ---------- ------------ --------- ------------- ----------
shared pool 1664 1664 1664 0 STATIC 32
large pool 64 64 64 0 STATIC 32
java pool 64 64 64 0 STATIC 32
streams pool 0 0 0 0 STATIC 32
DEFAULT buffer cache 10176 10176 10176 0 INITIALIZING 32
内存组件大小为1.6G+10G约为12G
所以如此一算,刚好和内存的大小一致。看来尽管sga,pga会显示有一个很大的值,其实还是根据实际的内存资源来分配。
这个时候问题就来了,为什么能够设置sga,pga为一个较高的值,而且数据库中似乎能够验证通过。
这个地方也就只能用kernel层面才可以说清了。
cat /etc/sysctl.conf的配置如下,可以看到配置了shmmax为近100G的最大共享内存段,支持的共享内存段的页数也非常高。shmall还是很高的。
fs.aio-max-nr = 1048576
kernel.shmall = 33554432
kernel.shmmax = 107374182400
kernel.shmmni = 4096
查看当前的session设置的shmmax的值。
# more /proc/sys/kernel/shmmax
107374182400
如果查看共享内存段的内容如下:
# ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x74010013 2293760 root 600 4 0
0x740182d0 2981889 root 600 4 0
0x00000000 4194306 oracle 640 134217728 67
0x740182cf 2949123 root 600 4 0
0x00000000 4227076 oracle 640 21340618752 67
0x538bd97c 4259845 oracle 640 2097152 67
0x00000000 3768326 oracle 640 67108864 49
0x00000000 3801095 oracle 640 12549357568 49
0xaf0a22e4 3833864 oracle 640 2097152 49
0x6c0109ec 6455305 zabbix 600 995952 6
所以内核参数的设置还是存在一定的问题,shmmax可以设置为内存的一半或者更高。一般会尝试用内存的80%等
#kernel.shmall = 33554432
#kernel.shmmax = 107374182400
kernel.shmall = 8388608
kernel.shmmax = 32212254720
比如可以设置为一个相对较大的值,使用getconf PAGE_SIZE得到的页大小一般都是4k.
那么我们来简单规范一下。
ctest数据库实例的设置为:
SQL> alter system set sga_max_size=12G scope=spfile;
System altered.
SQL> alter system set sga_target=12G scope=spfile;
System altered.
SQL> show parameter uniq
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_unique_name string STEST
SQL> show parameter pga
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_target big integer 4G
pga适度改小一些,然后停备库,听备库还有什么方法论吗,那就是看看session的情况,是否有其它额外的session在运行。
SQL> select username,count(*)from v$session group by username;
USERNAME COUNT(*)
------------------------------ ----------
42
PUBLIC 5
SYS 1
SQL> shutdown immediate 之后就需要使用sysctl -p或者重启服务器的方式来设置生效了。
没有sysctl -p之前,查看shmmax的设置还是100G
$ more /proc/sys/kernel/shmmax
107374182400
设置生效之后,再来看看swap的情况。发现一下子降下来了。
top - 17:34:47 up 154 days, 7:45, 2 users, load average: 0.33, 0.32, 0.28
Tasks: 211 total, 1 running, 204 sleeping, 0 stopped, 6 zombie
Cpu(s): 0.3%us, 0.3%sy, 0.0%ni, 99.2%id, 0.2%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 32949076k total, 3464424k used, 29484652k free, 193008k buffers
Swap: 8385920k total, 4352k used, 8381568k free, 2901552k cached
至于swap的监控,可以使用下面的脚本来做一些简单的分析,还算是比较实用的。
因为环境的swap使用很低,所以可以找一台服务器swap相对较高的,然后使用下面的脚本来分析。
# for i in $( cd /proc;ls |grep "^[0-9]"|awk ' $0 >100') ;do awk '/Swap:/{a=a+$2}END{print '"$i"',a/1024"M"}' /proc/$i/smaps 2>/dev/null ; done | sort -k2nr | head -10
19119 1503.39M
7520 50.7617M
18216 38.6172M
18218 26.3945M
18212 22.0938M
32219 11.8242M
18174 11.2539M
18286 7.8125M
18214 6.90625M
12507 5.17578M
可以看到哪个进程占用了较高的temp资源情况。
那么这儿问题如何验证,是否内核参数shmmax,shmall设置过高,会有sga_target设置的错觉。
SQL> show parameter sga
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
lock_sga boolean FALSE
pre_page_sga boolean FALSE
sga_max_size big integer 45G
sga_target big integer 45G
使用top -c查看的结果如下:
Tasks: 253 total, 1 running, 252 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 16319100k total, 5582080k used, 10737020k free, 429292k buffers
Swap: 16777200k total, 12956k used, 16764244k free, 4402968k cached
ipcs的情况可以参见下面的结果。
$ ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 6062080 oracle 640 67108864 17
0x00000000 6094849 oracle 640 12515803136 17
0xfadedb24 6127618 oracle 640 2097152 17
0x00000000 6848515 oracle 640 268435456 27
0x00000000 6881284 oracle 640 24024973312 27
0x00000000 6914053 oracle 640 24024973312 27
0xc3655edc 6946823 oracle 640 2097152 27