******************************************************************
今天遇到一個系統問題,系統內存不足,但是用VMSTAT 那些命令看,又看不到哪個進程在佔用內存。搞了很久沒找到原因,後來是因爲這個系統配置了hugepage,給賬號weblogic 分配了幾個G的內存,導致系統內存不足的原因,下面來詳細介紹下hugepage的配置方法。
******************************************************************
/etc/security/limits.conf:
weblogic soft memlock 6291456 (物理內存總和減2G) x*1024*1024
weblogic hard memlock 6291456
/etc/sysctl.conf:
kernel.shmmax = 7516192768 (cat /proc/meminfo | grep MemTotal:kb x 1024,可設爲物理內存大小)
這個值必須大於hugepage小於物理內存 x*1024*1024*1024
vm.hugetlb_shm_group = 500
vm.nr_hugepages = 2560 (5G)
groupadd -g 500 hugepage
usermod -G hugepage weblogic (將hugepage作爲weblogic的次要組)
grep -i hugepage /proc/meminfo
Hugepage、VLM、SGA和Share memory
由於新數據庫環境使用了一些VLM、hugepage相關的一些技術,因此花了幾天時間研究了一些這些東西,並記錄與大家分享。如有不對之處請指出。
一、相關概念
Hugepage/Big page:
系統進程是通過虛擬地址訪問內存,但是CPU必須把它轉換程物理內存地址才能真正訪問內存。爲了提高這個轉換效率,CPU會緩存最近的虛擬內存地址和物理內存地址的映射關係,並保存在一個由CPU維護的映射表中。爲了儘量提高內存的訪問速度,需要在映射表中保存儘量多的映射關係。
而在Redhat Linux中,內存都是以頁的形式劃分的,默認情況下每頁是4K,這就意味着如果物理內存很大,則映射表的條目將會非常多,會影響CPU的檢索效率。因爲內存大小是固定的,爲了減少映射表的條目,可採取的辦法只有增加頁的尺寸。這種增大的內存頁尺寸在Linux 2.1中,稱爲Big page;在AS 3/4中,稱爲Hugepage。
如果系統有大量的物理內存(大於8G),則物理32位的操作系統還是64位的,都應該使用Hugepage。
注意:使用Hugepage內存是共享內存,它會一直pin在內存中的,不會被交換出去,也就是說使用hurgepage的內存不能被其他的進程使用,所以,一定要合理設置這個值,避免造成浪費。對於只使用Oracle的服務器來說,把Hugepage_pool設置成SGA大小即可。
VLM(Very Large Memory ):這個是要是針對32位的操作系統,對於64位操作系統,則需要設置VLM。在啓用了Hugepage的情況下,32位的ORACLE可以把SGA擴展到62G。需要注意的是,VLM只對SGA中buffer cache有效,對shared pool、large pool、java pool等無效。
VLM的原理是把內存虛擬程一個文件,系統進程通過讀取這個內存文件達到使用內存的目的。
如果ORACLE想要使用VLM,則必須設置參數use_indirect_data_buffers=true。如果是10g的數據庫,還需要把db_cache_size轉換成老版本的db_block_buffers,否則會報錯。
當SGA使用VLM時,SGA對應的共享內存會分成兩個部分:
. 普通的系統共享內存,也就是可以從ipcs -ma看到的部分,這部分主要對應非buffer cache的SGA(large pool/shared pool/java pool/streams pool)等。
. 基於內存文件的共享內存,這部分可以通過ls -al /dev/shm查看。這部分主要對應SGA中的data buffer部分。
注意:使用VLM時,用於非buffer cache部分的內存會保留512M用於管理VLM。如如果分配了2.5G給非buffer cache使用,實際上,只有2G的實際可用內存。
當使用VLM時,以上兩個部分共享內存之和等於SGA。(如果不使用VLM,則SGA大小就等於ipcs -ma顯示的大小基本一致)
下面舉一個例子說明這四者的關係:
1、SGA相關
SQL> show sga
Total System Global Area 1879048192 bytes
Fixed Size 778452 bytes
Variable Size 802430764 bytes
Database Buffers 1073741824 bytes
Redo Buffers 2097152 bytes
-----非BUFFER CACHE部分
SQL> show parameter shared_pool_size
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
shared_pool_size big integer 512M
SQL> show parameter java_pool_size
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
java_pool_size big integer 32M
SQL> show parameter large_pool_size
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
large_pool_size big integer 128M
SQL> show parameter streams_pool_size
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
streams_pool_size big integer 80M
SQL> show parameter log_buffer
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
log_buffer integer 2097152
-----BUFFER CACHE部分
SQL> show parameter block_size
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_block_size integer 8192
SQL> show parameter db_block_buffers
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_block_buffers integer 131072
2、ipcs顯示的大小
$ipcs -a
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0xf258e130 32769 oracle 600 807403520 0
0x00000000 65538 oracle 640 4096 0
------ Semaphore Arrays --------
key semid owner perms nsems
0x610520f4 98304 oracle 640 602
0x610520f5 131073 oracle 640 602
0x610520f6 163842 oracle 640 602
------ Message Queues --------
key msqid owner perms used-bytes messages
3、/dev/shm大小
$ls -al /dev/shm
total 120
drwxrwxrwt 1 root root 0 Feb 15 02:11 .
drwxr-xr-x 22 root root 118784 Feb 15 02:11 ..
-rw-r----- 1 oracle dba 1073741824 Feb 15 02:12 ora_test_65538
(shared_pool_size + java_pool_size + large_pool_size + streams_pool_size + log_buffer) = (512 + 32 + 128 + 80)*1024*1024+2097152=790626304 和ipcs的結果807403520基本一致。
131072*8192=1073741824 和ls -al /dev/shm的結果1073741824相等。
這個結果也驗證了以上我們做的結論。
二、配置Hugepage
因爲使用hugepage部分的共享內存不能被swap,也不能被其他進程使用,如果把hugepage共享內存設置過大,會導致系統hang住。
既要考慮性能,又要不浪費內存,一定要把使用hugepage部分的共享內存設置一個最佳值。下面的一些參考:
1) 如果是32位操作系統,且沒有用VLM,則設置 hugetlb_pool=所有運行在該服務器上的實例SGA總和。如果有ASM,則每一個ASM實例再增加200M左右
2) 如果是32位操作系統,且使用了VLM,則設置 hugetlb_pool=所有運行在該服務器上的實例除data buffer外的SGA總和。如果有ASM,則每一個ASM實例再增加200M左右
3) 如果是64位操作系統,不管是否啓用VLM,都設置 hugetlb_pool=所有運行在該服務器上的實例SGA總和。如果有ASM,則每一個ASM實例再增加200M左右
在RHEL 2.1/3/4設置Hugepage的方法各不一樣,因爲2.1版本太低,這裏就不介紹了。
1、在RHEL3中設置hugepage
很簡單,只需要在/etc/sysctl.conf添加如下行即可:
#設置1024M hugepage momory
vm.hugetlb_pool=1024
執行sysctl -p使得修改生效。
此時從/proc/meminfo中可以驗證設置是否生效:
$more /proc/meminfo |grep -i HugePage
HugePages_Total: 512
HugePages_Free: 512
Hugepagesize: 2048 kB
因爲設置的1024M的hugepage_pool,每頁2M,所以會有512頁。
理想情況下,當oracle實例啓動後,HugePages_Free應等於或者接近0。
2、在RHEL4中設置hugepage
類似於RHEL3,在RHEL4配置hugepage也很簡單,
1)在/etc/sysctl.conf添加如下行:
#設置1024M hugepage momory
vm.nr_hugepages=512
在RHEL4中,是直接設置hugepage的頁數。
執行sysctl -p使得修改生效。
2) 在/etc/security/limits.conf 添加如下行
oracle soft memlock 1048576
oracle hard memlock 1048576
必須設置這個,否則啓動數據庫可能會報錯:
ORA-27103: internal error
Linux Error: 11: Resource temporarily unavailable
此時從/proc/meminfo中可以驗證設置是否生效:
$more /proc/meminfo |grep -i HugePage
HugePages_Total: 512
HugePages_Free: 512
Hugepagesize: 2048 kB
理想情況下,當oracle實例啓動後,HugePages_Free應等於或者接近0。
如果不想設置hugepage,則設置vm.nr_hugepages=0即可。
有幾點需要注意:
1) 無論RHEL3還是RHEL4,只要設置了hugepage_pool或者nr_hugepages,都意味着指定尺寸的內存被pin在內存中了。就算SGA需要的共享內存小於設置的hugepage_pool,這部分內存也無法被其他進程使用,所以,一定要計算好需要的大小,不宜設置過大的hugepage共享內存,避免浪費。
三、配置VLM
在RHEL3和RHEL4中,可以使用兩種內存文件方式配置VLM:
. shmfs/tmpfs:這個內存文件方式會發生換頁,與hugepage衝突,不適用於使用hugepage的內存管理方式。其中shmfs只適用於RHEL3,tempfs適用於RHEL3和RHEL4。
. ramfs:這種方式不會發生換頁,可以與hugepage搭配使用。
要配置VLM,系統內核必須支持以上三種文件系統之一,可以用以下命令判斷:
egrep "shm|tmpfs|ramfs" /proc/filesystems
如果結果有對應的條目輸出,則表示支持該類型文件系統,如:
nodev tmpfs
nodev ramfs
表示內存支持tmpfs和ramfs兩種內存文件系統。
下面以爲一個32位的數據庫配置8G大小的buffer cache爲例說明如何在RHEL3/4中配置VLM(首先要保證內核支持並已經配置Hugepage)
1、掛載內存文件系統
umount /dev/shm
mount -t ramfs ramfs /dev/shm
chown oracle:dba /dev/shm
注意
1)爲了重啓後也生效,最好把以上幾行寫在/etc/rc.local裏
2)如果oracle用戶的主組不是dba,如是oinstall,則chown oracle install /dev/shm
2、修改oracle參數
use_indirect_data_buffers=true
db_block_size=8192
db_block_buffers=1048576
shared_pool_size=2831155200
3、修改oracle的資源限制
在/etc/security/limits.conf中設置memlock=3145728,也就是在該文件中添加如下兩行:
oracle soft memlock 3145728
oracle hard memlock 3145728
用ulimit -l驗證
使用VLM時:
1) 無論是什麼版本,不能用db_cache_size參數,必須轉換成對應的db_block_buffers和db_block_size
2) data buffer部分的共享內存來自VLM,但SGA的其他部分,如shared_pool使用的共享內存來自系統的普通共享內存。
3) kernel.shmmax的設置應大於等於除data buffer以外的其他SGA部件之和
4) 不必像設置hugepage_pool那樣考慮要位data buffer設置多大的共享內存,操作系統會自動生成一個與設置的data buffer一樣大小的內存文件
5) 即使hugepage足夠大,data buffer需要的共享內存也不會從hugepage_pool中分配,而是使用VLM內存文件擴展共享內存段
6) 即使hugepage不足,非data buffer部分的SGA需要的共享內存也不會從VLM中分配,而是使用系統其他的空閒內存擴展共享內存段
最後做一個簡單總結:
1、hugepage是爲了提高內存的性能;VLM是爲了使32位操作系統使用大內存
2、如果服務器上有大量物理內存:
如果是64位的操作系統,只需要設置hugepage即可,且可以使用db_cache_size這一新參數。
如果是32位的操作系統,需要配置hugepage和VLM,並且不能使用db_cache_size這一新參數。其中hugepage_pool設置爲非buffer cache的內存總和大小。buffer cache對應的共享內存部分無需設置,OS會自動分配適當大小的內存文件作爲共享內存。