読者です 読者をやめる 読者になる 読者になる

kenken0807_DBメモ

つば九郎が好きなDBAです。Oracle Standard Editionでの運用やツールとかとかの備忘録。特に記載がない場合はoracle11gR2です。時々MySQL

Oracle常駐接続プーリング(DRCP)を導入して苦労したメモ(2)

2. 初期プールサーバ数ではまったこと

初期プールサーバ数デフォルトで検証

DBA_CPOOL_INFOビューで確認すると、
maxsizeがデフォルト40であり、これは変更しなくてはいけないものだというのはわかるが、
minsizeがデフォルト4で接続が足りないとincrsizeがデフォルト2づつmaxsizeまで増えていくので 、大丈夫だろうとminsizeはそのままで検証していた。

まず、maxsizeを変更する

execute dbms_connection_pool.configure_pool( null,maxsize=>2000);

これで専用サーバ接続とDRCP接続をどれだけ違いがでるか比較したみた。
perlのparallel::forkmanagerを使用して、
10000クエリ(PK引きのselect文)×5回ループ(パラレル度20)で実行した。
実行時間とstatspackの気になった項目結果を見ると、

パラメータ名 専用サーバ DRCP
実行時間 8m30.600s 9m47.641s
CPU time 354 262
DB CPU 1,625.2 319.6
cmon timer 0 606
execute count 518,219 766,873
recursive calls 6,190,765 8,381,095
OS process 200,309 327
cp cmon/server latch 1 1,399,734

OS processや`CPUの使用時間はDRCPのほうが小さいが、
まさかの実行時間が専用サーバのほうがはやかった
execute countrecursive callsが増えたのはDRCPが内部でなにかやってるのだろうとは思うが。

V$CPOOL_STATSビューを確認したところ、 NUM_OPEN_SERVERSがデフォルトの4のままで増えていない、NUM_WAITSが49977で実行したのが50000クエリなのでほとんどのクエリが待たされているのがわかる。

初期プールサーバ数を増やして検証

minsizeを200にあげて同様の処理を実行してみると、

execute dbms_connection_pool.configure_pool( null,minsize=>200);

実行時間が8m30.412sNUM_WAITS7830まで減っていた。

よって、minsizeを同時接続数分またはそれよりも多くとっておくことで処理速度が早くなる模様。
minsizeが少なければNUM_WAITSが増えて、incrsizeでプールサーバが新規生成するよりも待った方が良いと判断するのかも。 デフォルトのminsizeを大きめにとっておいたほうが無難そうである。

3. 高負荷時のエラーではまったこと

DRCPの負荷テストをしていた際に、
同時接続数を徐々にあげていって耐えれるのか検証していた。
とある時点で、接続できなくなる現象が起こり、listener.logを確認すると

29-7月 -2015 16:01:13 * (CONNECT_DATA=(CID=(PROGRAM=JDBC Thin Client)(HOST=__jdbc__)
(USER=oracle))(service_name=XXX)(server=pooled)) * (ADDRESS=(PROTOCOL=tcp)
(HOST=127.0.0.1)(PORT=40927)) * establish * XXX * 12518
TNS-12518: TNS: リスナーはクライアント接続をハンドオフできません。
 TNS-12564: TNS: 接続が拒否されました。
  TNS-12602: TNS: 接続プールの制限に達しました
   TNS-00524: 現行の操作が進行中です。
    Linux Error: 115: Operation now in progress

が頻発し、リスナー状態を確認すると拒否が大量に発生してしまっている。

$ lsnrctl service | grep NO
      "N000" 確立:265002 拒否:208475 現行:78 最大:40000 状態:ready

こうなってしまうと、sqlplusでもリスナー経由で接続できなくなってしまった・・・。
ちなみに専用サーバ接続でDRCPのエラー発生時点の同時接続数で試したところ、エラーにならない。。

調査していく中で、接続ブローカーが怪しい。
num_cbrokがデフォルトでは1となっている。

num_cbrokを2に変更する。

exec DBMS_CONNECTION_POOL.ALTER_PARAM('SYS_DEFAULT_CONNECTION_POOL', 'NUM_CBROK', '2');

リスナー状態を確認すると増えているのがわかる。

$ lsnrctl service | grep NO
      "N000" 確立:265002 拒否:208475 現行:78 最大:40000 状態:ready
   "N001" 確立:0    拒否:0      現行:0  最大:40000 状態:ready

結果、リスナーの拒否もなくなり、正常に処理できるようになった。

DRCPの最適なnum_cbrokを把握するには、
同時接続数の負荷を与えながら↓のようにリスナーを監視して拒否が出ない値を探しながら設定したほうがいいかも。

watch -n 2 "lsnrctl service | grep N0"

次回は監視方法など。