一條關於swap爭用的報警郵件分析(二)

jeanron100發表於2016-02-09

最近收到報警,某一個伺服器的swap空間有些緊張,檢視這臺伺服器上有兩個備庫資料庫例項,當然負載還是很低的。但是目前來看,記憶體已經所剩無幾,所以自然而然會用到swap,而且swap也看起來緊張了,從設計的角度來看,這種方式還是有很大的隱患,一旦需要切換,這臺伺服器還是很有可能出現oom-killer的情況,也就意味著當機。所以從小從大來看這個報警都不能掉以輕心。
   使用
top檢視的情況如下,可以看到swap已經很緊張了,剩餘記憶體不到300M了。

top - 13:46:44 up 973 days,  3:00,  1 user,  load average: 0.23, 0.16, 0.10

Tasks: 884 total,   1 running, 880 sleeping,   0 stopped,   3 zombie

Cpu(s):  0.9%us,  0.6%sy,  0.0%ni, 98.5%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st

Mem:  65923168k total, 65624684k used,   298484k free,  1256944k buffers

Swap: 33554424k total, 23177916k used, 10376508k free, 60284668k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                

 6821 oracle    20   0 16.2g  57m  53m S  9.9  0.1   3618:47 ora_rsm0_megdb                                                        

 4768 oracle    20   0 40.9g 109m  94m S  1.3  0.2  18619:36 ora_dia0_tebdb2    

檢視當前伺服器的資料庫例項情況,如下,可以結合上面的情況可以看到SGA應該一個是40G,一個是16G.

 [oracle@stepay2 ~]$ ps -ef|grep smon

oracle    4784     1  0  2013 ?        00:24:15 ora_smon_tebdb2

oracle    6738     1  0  2014 ?        00:13:26 ora_smon_megdb

oracle   20793 20706  0 13:47 pts/2    00:00:00 grep smon

進一步檢視進行驗證,tebdb2SGA看似沒有啟用SGA的自動管理。

SQL> show parameter sga

NAME                                 TYPE        VALUE

------------------------------------ ----------- ------------------------------

lock_sga                             boolean     FALSE

pre_page_sga                         boolean     FALSE

sga_max_size                         big integer 41472M

sga_target                           big integer 0

檢視megdbSGA的情況,是使用了SGA的自動管理的。

SQL> show parameter sga

NAME                                 TYPE        VALUE

------------------------------------ ----------- ------------------------------

lock_sga                             boolean     FALSE

pre_page_sga                         boolean     FALSE

sga_max_size                         big integer 16G

sga_target                           big integer 16G

當然PGA也會消耗一些記憶體,但是這些消耗應該不會成為瓶頸,但是swap的消耗卻很高。

為什麼SGA+PGA的設定都在範圍之內,但是swap卻總是不夠用呢。

這個時候檢視共享記憶體段的情況,發現其中一個資料庫例項40GSGA貌似沒有體現出來。

[oracle@stepay2 trace]$ ipcs -m

------ Shared Memory Segments --------

key        shmid      owner      perms      bytes      nattch     status     

0x00000000 294912     oracle     640        4096       0                      

0x00000000 327681     oracle     640        4096       0                      

0x4ab8364c 360450     oracle     640        4096       0                      

0x00000000 1769475    oracle     640        100663296  67                     

0x00000000 1802244    oracle     640        17079205888 67                     

0xf6d1ab84 1835013    oracle     640        2097152    67  

所以對於這種情況,一種改善思路就是開大頁,從目前經歷的絕大多數Linux系統來說,大頁的設定應該是一個標配.當然Oracle官方也提供了相應的指令碼。

我簡單來說一下,指令碼的思路首先是根據核心版本,目前支援2.4,2.6

[oracle@stepay2 trace]$ uname -r | awk -F. '{ printf("%d.%d\n",$1,$2); }'

2.6

然後得到一個page size的大小,也可以使用root許可權透過getconf PAGESIZE來得到。

[oracle@stepay2 trace]$ grep Hugepagesize /proc/meminfo | awk {'print $2'}

2048

然後透過ipcs –m得到共享記憶體段的情況,然後根據共享記憶體段的資料來計算需要設定的大頁核心引數設定。

[oracle@stepay2 trace]$ ipcs -m | awk {'print $5'} | grep "[0-9][0-9]*"

4096

4096

4096

100663296

17079205888

2097152

因為我們的環境是多例項,我們可以設定一個統一的值,比如我們需要設定50G左右的大頁,就可以使用下面的公式進行計算。

MIN_PG=`echo "51200000000/(2048*1024)" | bc -q`

透過上面的公式就會輸出最終建議的大頁設定

[oracle@stepay2 trace]$ echo "51200000000/(2048*1024)" | bc -q

24414

對應的核心引數在核心2.6就是 vm.nr_hugepages=24414

簡單的環境設定交代完畢,然後準備重啟備庫資料庫例項,同時考慮到資源的使用情況,把原來40GSGA調整為32G,然後把兩個例項都停了之後,swap的使用率一下子降下來了。

Tasks: 821 total,   1 running, 817 sleeping,   0 stopped,   3 zombie

Cpu(s):  0.9%us,  0.4%sy,  0.0%ni, 98.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st

Mem:  65923168k total, 53194676k used, 12728492k free,    63904k buffers

Swap: 33554424k total,    32812k used, 33521612k free,  1694992k cached

然後我們重啟,這個時候發現有一個資料庫例項怎麼都啟動不了。

SQL> startup nomount

ORA-27102: out of memory

Linux-x86_64 Error: 28: No space left on device

一般根據經驗這個錯誤主要都是因為核心引數設定的過小導致。

但是檢視了/etc/sysctl.conf的配置,沒有發現問題。

kernel.shmmax = 68719476736

kernel.shmall=16777216 

fs.aio-max-nr = 1048576

fs.file-max = 6815744

vm.nr_hugepages= 24414

對於這個問題著實感到奇怪,同時檢視alert日誌也沒有看到任何大頁開啟的資訊。為什麼大頁沒有開啟呢,而且資料庫例項還啟動不了。

這個可以從共享記憶體段的設定情況來做一個簡單的佐證。

[oracle@stepay2 ~]$ ipcs -m

------ Shared Memory Segments --------

key        shmid      owner      perms      bytes      nattch     status     

0x00000000 2260995    oracle     640        201326592  0                      

0x00000000 2293764    oracle     640        32010928128 0    

    發現其中一個設定為32G的共享記憶體空間已經被使用了,而且更加奇怪的是切換profile使用sqlplus還連線不到這個例項,可見這部分記憶體空間還沒有透過ORACLE_SIDSGA建立對映關係。那麼對於這部分快取空間,可以手工進行清理。

[oracle@stepay2 ~]$  ipcrm -m  2293764   

而為什麼大頁沒有開啟呢,這個時候反覆驗證,發現是啟用了自動記憶體管理,明白了這點再來看這個問題一下子就有些恍然大悟了。把這臺伺服器上相關的服務都停了,然後手工清空了剩餘的共享記憶體段。

[oracle@stepay2 ~]$ ipcs -m

------ Shared Memory Segments --------

key        shmid      owner      perms      bytes      nattch     status     

0x00000000 2260995    oracle     640        201326592  0                      

[oracle@stepay2 ~]$ ipcrm -m 2260995

當然如果條件允許,最好重啟一下,如果不能重啟還是使用sysctl –p來設定核心引數生效。

然後再次重啟就沒有任何問題了。

[oracle@stepay2 trace]$ ipcs -m

------ Shared Memory Segments --------

key        shmid      owner      perms      bytes      nattch     status     

0x00000000 3506176    oracle     640        100663296  67                     

0x00000000 3538945    oracle     640        16005464064 67                     

0xf6d1ab84 3571714    oracle     640        2097152    67                     

0x00000000 3637251    oracle     640        201326592  66                     

0x00000000 3670020    oracle     640        32010928128 66                     

0x4ab8364c 3702789    oracle     640        2097152    66                      

透過這個細小的案例,我們可以看到其實有些看似細小的警告,如果不加以重視,會逐漸演變為一個大問題。需要提前預警,提前處理。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-1987495/,如需轉載,請註明出處,否則將追究法律責任。

相關文章