まず oracle プロセスのメモリマップを見てみましょう。 それは /proc/PID の下の maps にあります。
> uname -a Linux cometeor 2.4.9-e.24 #1 Tue May 27 16:15:51 EDT 2003 i686 unknown > ps -ef|grep ora_|grep -v grep ora920 32373 1 0 Dec15 ? 00:00:00 ora_pmon_ora920 ora920 32375 1 0 Dec15 ? 00:00:00 ora_dbw0_ora920 ora920 32377 1 0 Dec15 ? 00:00:00 ora_lgwr_ora920 ora920 32379 1 0 Dec15 ? 00:00:00 ora_ckpt_ora920 ora920 32381 1 0 Dec15 ? 00:00:03 ora_smon_ora920 ora920 32383 1 0 Dec15 ? 00:00:00 ora_reco_ora920 > cd /proc/32373 > ls -l total 0 -r--r--r-- 1 ora920 dba 0 12月 16 09:09 cmdline lrwxrwxrwx 1 ora920 dba 0 12月 16 09:09 cwd -> /home/ora920/app/oracle/product/9.2.0/dbs -r-------- 1 ora920 dba 0 12月 16 09:09 environ lrwxrwxrwx 1 ora920 dba 0 12月 16 09:09 exe -> /home/ora920/app/oracle/product/9.2.0/bin/oracle dr-x------ 2 ora920 dba 0 12月 16 09:09 fd -rw------- 1 ora920 dba 0 12月 16 09:09 mapped_base -r--r--r-- 1 ora920 dba 0 12月 16 09:09 maps -rw------- 1 ora920 dba 0 12月 16 09:09 mem -rw------- 1 ora920 dba 0 12月 16 09:09 oom_priority lrwxrwxrwx 1 ora920 dba 0 12月 16 09:09 root -> / -r--r--r-- 1 ora920 dba 0 12月 16 09:09 stat -r--r--r-- 1 ora920 dba 0 12月 16 09:09 statm -r--r--r-- 1 ora920 dba 0 12月 16 09:09 status > cat mapped_base 1073741824 (0x40000000) > cat maps 08048000-0a4ba000 r-xp 00000000 03:41 4571224 /home/ora920/app/oracle/product/9.2.0/bin/oracle <-- text segment 0a4ba000-0ad53000 rw-p 02471000 03:41 4571224 /home/ora920/app/oracle/product/9.2.0/bin/oracle <-- data segment 0ad53000-0ade8000 rwxp 00000000 00:00 0 <-- BSS data segment <-- mapped_base 40000000-40016000 r-xp 00000000 03:03 4734983 /lib/ld-2.2.4.so 40016000-40017000 rw-p 00015000 03:03 4734983 /lib/ld-2.2.4.so 40017000-40018000 rw-p 00000000 00:00 0 40018000-40019000 r-xp 00000000 03:41 4391054 /home/ora920/app/oracle/product/9.2.0/lib/libodmd9.so 40019000-4001a000 rw-p 00000000 03:41 4391054 /home/ora920/app/oracle/product/9.2.0/lib/libodmd9.so 4001a000-4001c000 r-xp 00000000 03:41 4390927 /home/ora920/app/oracle/product/9.2.0/lib/libskgxp9.so 4001c000-4001d000 rw-p 00001000 03:41 4390927 /home/ora920/app/oracle/product/9.2.0/lib/libskgxp9.so 4001d000-4001f000 r-xp 00000000 03:41 4391051 /home/ora920/app/oracle/product/9.2.0/lib/libskgxn9.so 4001f000-40020000 rw-p 00001000 03:41 4391051 /home/ora920/app/oracle/product/9.2.0/lib/libskgxn9.so 40020000-402ff000 r-xp 00000000 03:41 4391044 /home/ora920/app/oracle/product/9.2.0/lib/libjox9.so 402ff000-4040f000 rw-p 002de000 03:41 4391044 /home/ora920/app/oracle/product/9.2.0/lib/libjox9.so 4040f000-40411000 rw-p 00000000 00:00 0 40411000-40414000 r-xp 00000000 03:03 4734996 /lib/libdl-2.2.4.so 40414000-40415000 rw-p 00002000 03:03 4734996 /lib/libdl-2.2.4.so 40415000-40437000 r-xp 00000000 03:03 4734998 /lib/libm-2.2.4.so 40437000-40438000 rw-p 00021000 03:03 4734998 /lib/libm-2.2.4.so 40438000-40439000 rw-p 00000000 00:00 0 40439000-40448000 r-xp 00000000 03:03 4735028 /lib/libpthread-0.9.so 40448000-4044c000 rw-p 0000e000 03:03 4735028 /lib/libpthread-0.9.so 4044c000-4046c000 rw-p 00000000 00:00 0 4046c000-4047f000 r-xp 00000000 03:03 4735001 /lib/libnsl-2.2.4.so 4047f000-40480000 rw-p 00012000 03:03 4735001 /lib/libnsl-2.2.4.so 40480000-40482000 rw-p 00000000 00:00 0 40482000-405b7000 r-xp 00000000 03:03 4734992 /lib/libc-2.2.4.so 405b7000-405bc000 rw-p 00134000 03:03 4734992 /lib/libc-2.2.4.so 405bc000-405e4000 rw-p 00000000 00:00 0 405e4000-40664000 rw-p 00000000 03:03 70990 /dev/zero 40664000-4066e000 r-xp 00000000 03:03 4735017 /lib/libnss_files-2.2.4.so 4066e000-4066f000 rw-p 00009000 03:03 4735017 /lib/libnss_files-2.2.4.so 4066f000-406b0000 rw-p 00000000 00:00 0 50000000-56c00000 rw-s 00000000 00:04 229380 /SYSV9645cf3c <-- SGA 56c00000-56c01000 r--s 06c00000 00:04 229380 /SYSV9645cf3c 56c01000-56ca2000 rw-s 06c01000 00:04 229380 /SYSV9645cf3c 56ca2000-56ca3000 r--s 06ca2000 00:04 229380 /SYSV9645cf3c 56ca3000-57000000 rw-s 06ca3000 00:04 229380 /SYSV9645cf3c bffe4000-bffee000 rwxp ffff7000 00:00 0 <-- stack
上記マップの説明は以下のとおりです。
これから mapped_base より低いアドレス部分と SGA
より高アドレス部分に空きがあることがわかります。
この未使用部分を SGA として利用するために再配置するのが、
はじめに説明する方法です。
またメモリの属性は以下のとおりです。(linux/ipc/shm.c remove_attach())
r | read |
---|---|
w | write |
x | execute |
s | share |
p | private |
RedHat Linux Advanced Server 2.1 (Enterprise kernel on IA-32) では物理アドレスを 36bit 扱えるので、最大 64GB までがアドレス可能です。 もちろん SGA を拡張しても、実装されているメモリ量が少なければ効果はありません。
上記以外のバージョンでは、32bit アドレス (4GB) ですので、
SGA の最大サイズは 2.7 GB (0xc0000000 - 0x15000000 = 0xa6000000) です。
正確には 2.7GB - stack サイズです。
そのうち mapped_base を変更しない場合は 1.7GB (0xc0000000 - 0x50000000 = 0x70000000) です。
SGA(共有メモリ)の拡張方法には、以下の2つがあります。
通常のアーキテクチャでも可能な方法ですが、最大 2.7 GB までしか拡張できません。 それは 32bit アドレスでは 4GB までですので、 そのうちの SGA の最大は 2.7 GB です。 ただし、実メモリが 4GB ないと効果はありません。
この方法は、oracle の実行モジュールの SGA のマップ開始アドレスをさげることで実現できます。
VLM (Very Large Memory) を使用すると最大 64GB まで拡張可能です。
そこで SGA の一部である buffer cache (db_block_size * db_block_buffers)
を VLM で実現します。
buffer cache のサイズがかなり大きくなりますので、
パフォーマンスの低下が問題になります。
その問題を回避するために、同時に bigpages の機能と設定方法も説明します。
ただし、この機能を利用するためには実メモリが充分あり、
しかも RedHat Linux Advanced Server 2.1 (Enterprise kernel)
である必要があります。
Enterprise kernel は Linux AS 2.1 2.4.9-e.25 以上
がインストールされていることをお薦めします。
> uname -a システム名を表示 > rpm -q kernel-enterprice enterprice kernel がインストールされているかの確認 > /sbin/sysctl -a 現在の kernel の設定値を表示
# echo 2147483648 >/proc/sys/kernel/shmmax 現在値の変更 # echo kernel.shmmax = 2147483648 >> /etc/sysctl.conf reboot 後の変更の反映
oracle ユーザとしてログインしたときのシェルの PID を求め、 その mapped_base を変更します。
# echo 268435456 > /proc/$PID/mapped_base
> cd $ORACLE_HOME/rdbms/lib > cp ksms.s ksms.s.org オリジナルをバックアップ > genksms -s 0x15000000 > ksms.s SGA のマップ開始アドレスを変更 > make -f ins_rdbms.mk ksms.o オブジェクトを作成 > make -f ins_rdbms.mk ioracle oracle をリリンク
SGA の一部であるバッファキャッシュ (db_block_size * db_block_buffers) の拡張を行うためには、以下の方法があります。
shmfs はメモリをファイルシステムにマップしたもので、 バッファキャッシュを共用メモリのように扱う方法の1つです。
以下の手順で作成します。
共有メモリのサイズを大きくした場合は、 それらを扱うために負荷がかかりますので、 メモリを扱う単位であるページを大きくするための bigpages を設定することをお薦めします。
Linux のデフォルトのページサイズは 4KB ですが、 そのサイズを大きくして (2MB or 4MB) OS が扱うページ数を少なくすると高効率となります (ページは OS がメモリを管理するための最小単位です)。
bigpage のページサイズは Linux 4GB kernel では 4MB で、 Linux 64GB kernel では 2MB です。 また bigpages を指定したメモリ部分は swapout されません。
shmfs を含む SGA を bigpages として扱うには、以下の設定が必要です。
/etc/sysctl.conf に以下の設定を追加します。
kernel.shm-use-bigpages = 2 0: SGA を bigpages として扱いません。 1: SGA を systemV ipc かつ bigpages として扱います。 2: バッファキャッシュ (shmfs) を含む SGA を bigpages として扱います。
確認は以下のとおりです。
cat /proc/sys/kernel/shm-use-bigpages
下記の3つの設定をした後、OS を reboot し、 oracle を再起動してください。
SGA または shmfs のうち bigpages として扱いたいサイズを指定bigpages=XXXMB
kernel.shm-use-bigpages = 2
ここで指定したサイズは、これを超えた場合エラーとなる最大数で、 それ以外に影響はありません。 ただし shmfs の部分は含みません。
kernel.shmmax = 1073741824
use_indirect_data_buffer=true
上記設定をした場合は動的キャッシュ・パラメータ (DB_CACHE_SIZE, DB_xxK_CACHE_SIZE)を設定してはならず、 DB_BLOCK_BUFFERS パラメータを使用してデータベース・キャッシュ・ サイズを指定するようにご注意ください。)
cat /proc/<PID>/maps # cat /proc/pmon_PID/maps (抜粋) 405c7000-421c7000 rw-b 00000000 00:09 15920 /dev/shm/orashm_7471112 421c7000-42247000 rw-p 00000000 08:41 38713 /dev/zero 42247000-42251000 r-xp 00000000 08:41 475273/lib/libnss_files-2.2.4.so 42251000-42252000 rw-p 00009000 08:41 475273/lib/libnss_files-2.2.4.so 42252000-42293000 rw-p 00000000 00:00 0 50000000-50400000 rw-B 00000000 00:04 7340036 /SYSV00000000 (deleted) 51000000-52400000 rw-B 00000000 00:04 7372805 /SYSV00000000 (deleted) 53000000-54800000 rw-B 00000000 00:04 7405574 /SYSV00000000 (deleted) 55000000-56c00000 rw-B 00000000 00:04 7438343 /SYSVbfd9a630 (deleted)
上記の結果で、rw-B または rw-b の部分が bigpages であることを示します。
oracle を shutdown し、以下の設定後再起動すると設定が反映されますが、 OS reboot 後は reset されますので、上記の方法でシステムを設定してください。
下記の方法は、動的にシステムを変更する場合に有効です。
上記 1 に関しましては、以下の方法もあります。 1. /etc/lilo.conf bigpages=XXXMB ...... bigpages のサイズを指定 上記 2 に関しましては、以下の方法もあります。 2.1 # echo 2 > /proc/sys/kernel/shm-use-bigpages バッファキャッシュを shmfs かつ bigpages として扱います。 2.2 # echo 4000000000 >/proc/sys/kernel/shmmax 共有メモリとして使用したい最大サイズを指定します。(4GB)
デフォルト設定では、物理メモリは 0xC0000000 番地にストレートマッピングされる。
Linuxカーネルは物理メモリの先頭にロードされているため、 仮想空間上は0xC0000000番地に割付いているように見える。 Linuxカーネル空間は多重仮想化せず、このままの状態で動作する。
プロセスの空間は、0x0〜0xC0000000の間に、動的に生成される。 空間は各プロセス毎に独立した多重仮想として生成する。 仮想空間上では有効なページであっても、 そのページに物理ページが割り当てられてるとは限らない。 ディスク上のファイルのブロックや SWAPを指していたり、 実際にアクセスがあったときに0クリアした メモリを割り当てる指定になっていることもある。
以下の lowermap.c のプログラムを作成し、モードを変更後、 ログイン時に実行するようにします。
> make lowermap # chmod u+s lowermap # chown root lowermap # chgrp bin lowermap # cp lowermap /usr/local/bin
[ lowermap.c ]
/*----------------------------------------------------------------------- * lowermap.c * suid program to lower the mapped_base shared memory addr * Authors: Robert Hentosh, robert_hentosh@dell.com * Zafar Mahmood, zafar_mahmood@dell.com * * Copyright 2002 Dell Computer Corp. Distributed under the GPL * * # chmod u+s lowermap * # chown root lowermap * # chgrp bin lowermap ----------------------------------------------------------------------*/ #include#include #include #include #include #include #define NEW_MAPPED_BASE "0x10000000" #define NEW_SHMMAX "0xB2D05E00" #define PROGNAME "lowermap" int main( int argc, char *argv[] ) { pid_t ppid; char fname[256]; int fd,ret; int retval; /** should ignore signals in setuid() programs **/ signal( SIGCHLD, SIG_IGN ); signal( SIGCONT, SIG_IGN ); signal( SIGTSTP, SIG_IGN ); signal( SIGTTIN, SIG_IGN ); signal( SIGTTOU, SIG_IGN ); ret = setuid(0); #if 0 printf("setuid ret=%d\n",ret); #endif if (ret) perror( PROGNAME ); ppid = getppid(); sprintf( fname, "/proc/%u/mapped_base", ppid ); fd = open( fname, O_WRONLY ); if ( fd == -1 ) { /* possibly not on Red Hat Enterprise Linux */ fprintf( stderr, "Unable to open file: %s\n", fname ); perror( PROGNAME ); exit errno; } retval = write( fd, NEW_MAPPED_BASE, sizeof( NEW_MAPPED_BASE ) ); if ( retval == -1 ) { /* possibly lowermap is not setuid root */ fprintf( stderr, "Unable to modify mapped base.\n"); fprintf( stderr, "Verify program permissions and ownership.\n"); perror( PROGNAME ); exit errno; } close( fd ); printf( "Lowering mapped base for pid:%u to %s\n", ppid, NEW_MAPPED_BASE ); fd = open( "/proc/sys/kernel/shmmax", O_WRONLY ); if ( fd == -1 ) { fprintf(stderr, "Unable to modify maximum shared memory segment size.\n"); perror( PROGNAME ); exit errno; } retval = write( fd, NEW_SHMMAX, sizeof( NEW_SHMMAX ) ); if ( retval == -1 ) { fprintf(stderr, "Unable to modify maximum shared memory segment size.\n"); perror( PROGNAME ); exit errno; } close( fd ); printf( "Increased maximum shared memory segment size to %u\n", NEW_SHMMAX ); exit (0); }