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 count
やrecursive 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.412s
でNUM_WAITS
が7830まで減っていた。
よって、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"
次回は監視方法など。