動的SGAと自動メモリ管理に関する検証 その4

投稿日: 2004年8月11日

<動的SGAと自動メモリ管理に関する検証 その4>
ペンネーム:アイスケーキ

今回も引き続き動的SGAと自動メモリ管理について検証をします。

◆環境
Windows XP Pro + SP1
Oracle Database 10g Enterprise Edition Release 10.1.0.2.0 – Prod

■メモリ拡縮のSGAコンポーネントについて
Oracle10gでは
○共有プール
○Javaプール
○ラージプール
○デフォルト・バッファキャッシュ
各SGAコンポーネントに対して個別にサイズを設定することなく初期化パラメ
ータ(sga_target)を使用しSGAの合計サイズのみを指定することで各コンポ
ーネントサイズを自動調整する機能が追加されました。

(このコンポーネントは各サイズを指定する初期化パラメータを設定しない場
合でもシステムの負荷状況によって自動的にサイズが変更します。
実質、初期パラメータ値はコンポーネント最小サイズの保証でしかありません)

自動調整されるコンポーネントで領域が足りないと判断して自動的に領域拡張
が発生するのは共有プール、Javaプール、ラージプールでデフォルト・バッフ
ァキャッシュは常にメモリ供給元になります。

且つ、共有プール、ラージプール、Javaプールの各コンポーネント間でのメモ
リ領域の移動はありません。

早速検証してみます。
共有プールが不足したとシステムに認識させるため大量のSQL文を発行してラ
イブラリキャッシュヒット率を落としてみます。
(任意なテーブルを作成した後、PL/SQLでバインド変数を使わずに大量のSQL
を発行する。今回はinsert文を3千行)

BEGIN
    INSERT INTO TBL1(t1,t2,t3,t4) VALUES (i,(i*100),(i*100),(i*100));
    INSERT INTO TBL1(t1,t2,t3,t4) VALUES (i,(i*100),(i*100),(i*101));
    INSERT INTO TBL1(t1,t2,t3,t4) VALUES (i,(i*100),(i*100),(i*102));
  (中略。。。)
END;
/

コンポーネントの拡縮を確認します。

SQL>
select to_char(START_TIME,'YYYY/MM/DD HH24:MI:SS') as "処理時間",
COMPONENT as "コンポーネント",
OPER_TYPE as "操作",
(FINAL_SIZE-INITIAL_SIZE)/1024/1024 as "差分(MB)",
FINAL_SIZE/1024/1024 as "サイズ(MB)"
from V$SGA_RESIZE_OPS;

処理時間            コンポーネント       操作         差分(MB)  サイズ(MB)
------------------- -------------------- ------------ --------- ----------
2004/08/10 23:00:04 DEFAULT buffer cache SHRINK              -4         76
2004/08/10 23:00:04 shared pool          GROW                 4         40
2004/08/10 23:23:03 DEFAULT buffer cache SHRINK              -4         72
2004/08/10 23:23:03 shared pool          GROW                 4         44

上記は共有プールへの領域割当状況が出力されていますが常にバッファキャッ
シュから割り当てられていく状況が見えます。
単位は4KB(1グラニュル)の倍数で増減するようです。

■デフォルト・バッファキャッシュから割り当てが行われる場合
db_cache_sizeの下限までデフォルト・バッファキャッシュが縮小したら
その後はどうなるのでしょう?

現在のパラメータ値(初期パラメータで指定しました)

NAME                                 TYPE        VALUE
------------------------------------ ----------- -------
sga_max_size                         big integer 140M
sga_target                           big integer 128M
db_cache_size                        big integer 68M   ←下限値設定

現在のバッファプール値

SQL> select name,bytes/1024/1024 as "バイト(MB)"
from v$SGASTAT where name = 'buffer_cache';
NAME                       バイト(MB)
-------------------------- ----------
buffer_cache                       80

大量のSQL文を発行してライブラリキャッシュヒット率を落とします。
その後の縮小の結果です。

処理時間            コンポーネント       操作       差分(MB) サイズ(MB)
------------------- -------------------- ---------- -------- ----------
2004/08/11 16:22:42 DEFAULT buffer cache SHRINK           -4         76
2004/08/11 16:22:42 shared pool          GROW              4         40
2004/08/11 16:22:49 DEFAULT buffer cache SHRINK           -4         72
2004/08/11 16:22:49 shared pool          GROW              4         44
2004/08/11 16:24:14 DEFAULT buffer cache SHRINK           -4         68 ★
2004/08/11 16:24:14 shared pool          GROW              4         48

ライブラリキャッシュのRELOADSも6倍なりました。

NAMESPACE      GETS   GETHIT PINS   PINHIT RELOADS
-------------- ------ ------ ------ ------ -------
SQL AREA       18471   0.50  74567   0.61     6091

バッファキャッシュは68MBで縮小がとまりました。

SQL> select name,bytes/1024/1024 as "バイト(MB)"
  2  from v$SGASTAT where name = 'buffer_cache';
NAME                       バイト(MB)
-------------------------- ----------
buffer_cache                       68

思い切って動的変更してみます。共有プールを増やす操作をします。

SQL> alter system set shared_pool_size=49M;
alter system set shared_pool_size=49M
*
行1でエラーが発生しました。:
ORA-02097: parameter cannot be modified because specified value is invalid
ORA-04033: Insufficient memory to grow pool

駄目でした。確かに下限値がストッパーになっているようです。
よく見るとsga_targetの上限に掛かっているようです。

SQL> select trunc(sum(bytes)/1024/1024) from v$SGASTAT ;
TRUNC(SUM(BYTES)/1024/1024)
---------------------------
                        128

sga_target を sga_max_sizeまで広げてみます。

SQL> alter system set sga_target=140M;
システムが変更されました。

NAME                                 TYPE        VALUE
------------------------------------ ----------- ----------
sga_max_size                         big integer 140M
sga_target                           big integer 140M

もう一度、共有プールを拡張してみます。

SQL> alter system set shared_pool_size=49M;
システムが変更されました。

今度はできてしまいました。拡張結果を見ると
デフォルト・バッファキャッシュも領域が拡張されています。
デフォルト・バッファキャッシュの下限は常にsga_target(最大sga_max_size)
の上限となるように調整が行われているようです。

処理時間            コンポーネント       操作       差分(MB) サイズ(MB)
------------------- -------------------- ---------- -------- ----------
2004/08/11 16:22:42 DEFAULT buffer cache SHRINK           -4         76
2004/08/11 16:22:42 shared pool          GROW              4         40
2004/08/11 16:22:49 DEFAULT buffer cache SHRINK           -4         72
2004/08/11 16:22:49 shared pool          GROW              4         44
2004/08/11 16:24:14 DEFAULT buffer cache SHRINK           -4         68
2004/08/11 16:24:14 shared pool          GROW              4         48
2004/08/11 16:26:10 DEFAULT buffer cache SHRINK           -4         76  ★
2004/08/11 16:26:10 shared pool          GROW              4         52

また、デフォルト・バッファキャッシュが不足していても共有プールなど他の
コンポーネントを縮小してデフォルト・バッファキャッシュを増加させること
は無いようです。

おそらく

○バッファキャッシュは領域が不足する場合は待機となりエラーは起きない。
○バッファキャッシュ待機よりも共有プール等領域不足の方が深刻なため、
  共有プール等のサイズから割り当てると更に深刻な状況に陥るから。
○共有プール、ラージプール、Javaプール領域が足りない場合は
  ORA-4031(共有メモリーのstringバイトを割当てできません)、
  ORA-29554(メモリー不足状態でJavaが未処理です)でユーザ処理が失敗する
  程度だから。

と思われます。
上記についても検証の余地があるようですね。

来週は盆休みのため1週間お休みです

秋が恋しい茅ヶ崎より