ORA-12518まとめ

以下のエラーに関する顛末のまとめ
ORA-12518: TNS: リスナーはクライアント接続をハンドオフできませんでした


サポートからは以下の情報

          • -

WINDOWSプラットフォームでは、
PGA_AGGREGATE_TARGET, SORT_AREA_SIZEパラメータが大きめの値に設定されている等、
各スレッドが多くのメモリを消費し、プロセスに割り当て可能なメモリの上限に達してしまう際に出力される
また、このような状態でリスナーがクライアントからリクエストを受け取るとTNS-12518が発生し、
接続が不可となる(ことがある)

          • -


メモリ上限ってなによ?ってWin32プラットフォームではアプリに分け与えられるメモリは2Gまで。
それを超えるとお腹いっぱいになってしまうと。


っつてもなぁ。記録では1.5G程度の消費で多少の余裕はあるんだけどなぁ。
じゃぁってんで、PGA_AGGREGATE_TARGETを600Mまで減らしてたのだが、やはり発生する時がある。
(もちろん、カーネルでつかめるメモリを2Gから3Gへ増やす方法は
 あることはあるのだが、MSもOracle社も推奨してないということで却下)


取り敢えず、セッション絞っていこうかということで現在保留中。
PGAは結構奇妙な動きをすることが判明している


1.PGAの概要

PGAは、大きくわけで、CGAとUGAに分けられる。


1)UGA
UGAは、ソートやハッシュ結合などの作業領域として利用される。
したがって、ソートするデータハッシュ結合するデータ量が多くなると、
UGAのサイズは増加する傾向があると考えられる。


2)CGA
CGAは、カーソル変数や、バインド変数、配列は、スタックなどの
プログラム上の変数を保持する領域とされている。
しがたって巨大な配列や、数多くの変数、スタックサイズの増大なのにより
増加する傾向があると考えられる。


2.Windowsのメモリアーキテクチャ
32ビットアドレッシングでは、アプリケーションが利用できるメモリ空間が2GBまでとなっている。
(残り2BGはカーネルが利用しているためユーザアプリケーションでは、通常は利用できない。)
この制限が足かせとなり、oracle.exeが利用できるメモリは、2GBまでとなっている。
また、unix系とは異なり、v$processビューで確認できるプロセスは、
oracle.exeという1プロセス内の1スレッドという位置付けとなっている。
これは、専用サーバー接続の場合、clientからのセッションにより起動される専用サーバーが
oracle.exeの1スレッドになるということを意味する。


したがって、大雑把に考えると、
Oracleのインスタンスのサイズ(最大2GB)
 =Oracleバイナリサイズ+SGAのサイズ+PGAのサイズ


ということになる。
OracleのバイナリサイズとSGAのサイズは固定サイズとして求めることができるが、
PGAのサイズは接続してくるセッション数等により増減する。
ちなみに、現対象サーバでは、バイナリサイズ+SGAサイズの合計は、約1.3GB程度であるため
PGAとして、利用できる空きサイズは、約700MB強程度である。


この700MBを各セッションに割り振らなけれならないが、
PGAの割り振りについては、来る者は拒まない仕様となっているようだ。
(つまり後で記載するPGA_AGGREGATE_TARGETパラメータの意味を失うということ。
 少なくとも、パラメータの説明通りの動作はしていないということだ)
次に、PGAを制御する初期化パラメータとその機能について、調べた点について記載する。


3.PGAに関連するパラメータ(公開、非公開含む)


1)PGA_AGGREATE_TARGET
インスタンスでPGAに割り当てるメモリサイズの総量の目標値。
PGAのサイズの上限ではないことに注意すること。
したがって、来る者は拒まず、要求されれば、それ以上のサイズになることはある。


2)_PGA_LARGE_EXTENT_SIZE (隠しパラメータ)
隠しパラメータであるため、マニュアルには記載されていない。
この単位でPGA(UGA、CGAも)が確保割り当てられている模様。
デフォルトでは、1MB。オラクルのマニュアルには明確に記載されていないものの、
1スレッドを確保すると1MBをデフォルトで割り当てるとなっているのは
これを意味していることである可能性は高い。


3)_PGA_MAX_SIZE (隠しパラメータ)
これも隠しパラメータであることから、マニュアルには記載されていない。
しかし、情報によると、_PGA_MAX_SIZEは、1プロセスの割り当てられるPGAサイズの上限となっている。
このパラメータのデフォルトサイズは、200MB。

これ、テストしてみたら、PGA_AGGREGATEがいくつに指定していようが
ワンセッションあたり200MBまでなら、容赦なくメモリ食いまくるということが解った。



4.PGAの割り当てロジック


PGA_AGGREGATE_TARGETを含めたパラメータを基にOracleがどのようにPGAを割り当てているのか?


CGAに関する部分の記述はWebでは、見つけられなかったもののUGAに関する動きを
細かく書いているサイトは多数あった。(おら!オラ!Oracleとか)


1) UGAに関する動作
前述した通り、UGAはソートなどに利用される。
メモリ(つまりUGA)内で足りなくなれば、DISK(一時表領域を利用する)を利用して作業する
ことになる。


メモリ(UGA)内だけで処理できた場合は、statspackレポートなどPGAに関するレポートでは
optimalで処理できた回数としてレポートされる。
1回だけDISKを利用した場合には、1-passとしてレポートされ、
複数回DISKを利用した場合には、m-passとしてレポートされる。


このUGAのメモリ割り当ての仕様では、1プロセス(1スレッド)が利用できるUGAサイズの
最大値が各パラメータをもとに算出される。


PGA_AGGREGATE_TARGET*5% 及び
_PGA_MAX_SIZE*50%


から小さい方の値を1プロセス(1スレッド)で利用できるUGAの最大サイズとして制限している。


PGA_AGGREAGTE_TARGETを600MBとすると、PGA_AGGREGATE_TARGET*5=30MB。
_PGA_MAX_SIZE*0.5=100MBであるから、現時点で、1プロセス(1スレッド)が利用できる
UGAの最大サイズは、30MBと計算できる。


UGAだけから見た場合には、1スレッド最大30MBとして、空きメモリ700MBである場合
最大で23セッションが同時に実行できる計算となる。ただ必要なUGAが足りない場合には、
DISKを利用することになりメモリはそれ以上要求されない。


2) CGAについて
CGAの割り当てロジックについての記述は見当たらなかったが、UGAに割り当てた残りが、
CGAとして利用できることになる。
CGA自体のサイズを制限するパラメータは存在しないようなので、
_PGA_MAX_SIZEからUGAに割り当てる最大サイズのあまりが事実上の最大サイズということにある。


※※※※※※※※※※※※※※※※※
_PGA_MAX_SIZEを減らせば、1セッションあたりのPGAサイズは制御できるかも
しれないが、_PGA_MAX_SIZEは、ユーザのセッション以外にどのような影響があるのか
全く記載されていないため、安易にサイズを減らすことはできない。
Oracle社サポートからの指示・回答が無い限りは触るべきではなさそうだ・・・。
※※※※※※※※※※※※※※※※※


尚、CGA、UGA、を含めたPGAのサイズは前述した各サイズにある程度のオーバーヘッドを
含んだサイズとなるという記載がある。
(テスト結果からも_PGA_MAX_SIZEより若干大きなサイズになっていることは確認できた。)