カーソルのクローズ


運用監視をしていて気がついたのだが、オープンカーソルの数が増えているのだ。

SELECT COUNT(*) FROM V$OPEN_CURSOR;

COUNT(*)

                  • -

154


ま、まさかカーソルの解放漏れか???

ということで必死こいて調べてみたのだが、さっぱり分からない。


とりあえず問題のSQLを調べてみた。

SELECT
SID, SERIAL#, OSUSER, MACHINE, PROGRAM, USERNAME,SQL_TEXT
FROM
V$OPEN_CURSOR JOIN V$SESSION USING (SID)
WHERE
USERNAME IN ('HOGE');


SQL_TEXTはSQLは全部は出ないのだが、パターンは判明。
ストアドの内部で発行しているSQLのようだ。

ただ、ストアド内部では暗黙カーソルを利用しているのでカーソルの解放漏れが発生するというのは考え難い。
ドライバやTomcatのプーリングか?と思ったけどそんなレポートもどこにもない。



んで、ふと気がついて実験してみた。
こんなストアドを作成する。

SQLA:暗黙カーソルを利用し、重複しない250個のSQLを発行する
つまり
 SELECT 1 INTO N FROM DUAL;
 SELECT 2 INTO N FROM DUAL;
  ・・・
 SELECT 250 INTO N FROM DUAL;

SQLB:SQLAと重複しないさらに250個のSQLを発行する
つまり
 SELECT 251 INTO N FROM DUAL;
 SELECT 252 INTO N FROM DUAL;
  ・・・
 SELECT 500 INTO N FROM DUAL;

SQLC:SQLAともSQLBとも重複しない500個のSQLを発行する
つまり
 SELECT 501 INTO N FROM DUAL;
 SELECT 502 INTO N FROM DUAL;
  ・・・
 SELECT 1000 INTO N FROM DUAL;


9iではデフォルトのオープンカーソル数は300個である

SHOW PARAMETER open_cursors

NAME TYPE VALUE

                                                      • -

open_cursors integer 300


1.を実行したあと、そのセッションで2.を実行したあとの挙動がどうなるのかがポイントだ。

手順

1.現在のオープンカーソル数を調べる('SELECT COUNT(*) FROM V$OPEN_CURSOR;')
2.SQLAを実行
3.オープンカーソル数を調べる
4.SQLBを実行
5.オープンカーソル数を調べる
6.SQLCを実行
7.オープンカーソル数を調べる


結果

1.
COUNT(*)

                  • -

25

3.
COUNT(*)

                  • -

276

5.
COUNT(*)

                  • -

276

7.
COUNT(*)

                  • -

276

結果にはばらつきがあると思うが、1セッションの中では300個のカーソルを使いまわしている(=同じSQLが実行されれば再利用される?)ことが判明した。
「カーソルのクローズ」とはV$OPEN_CURSORからも消えることだと思っていたのだが、そうではなかったらしい。


コネクションプーリングをしていると、ふと思いついてオープンカーソルを調べて「カーソル解放漏れが!!!」とあわてないようにしよう。


複数セッションからそれぞれ実行すれば、このような結果も戻ってくる。

select count(*) from v$open_cursor;

COUNT(*)

                  • -

572

'open_cursors'の数はあくまで「1セッションあたり」のオープンカーソル数なので勘違いしてはいけない 壁|▽//)ゝテレテレ


課題
※再利用されるならば、「最大オープンカーソル数を超えました」はどのような場合にでるのだ?
※'open_cursors'を例えば10000とかにしたらパフォーマンスには影響するのか?
 =>マニュアルには必要なら増やせ、としか書いてないのでデメリットが不明。
※本当にカーソル解放漏れがあったらどう見分けるのだ?


参考
http://www.atmarkit.co.jp/fdb/rensai/oraobstacle07/oraobstacle07_1.html
http://www.beasys.co.jp/cs/support_news/product_troubleshooting/ORA-1000_Max_Open_Cursors_Pattern.html