[Oracle] ORA-01000エラーの原因特定のためにV$OPEN_CURSORを利用する | Archive Redo Blog

Archive Redo Blog

DBエンジニアのあれこれ備忘録

アプリケーションでのカーソルの閉じ忘れによって「ORA-01000: 最大オープン・カーソル数を超えました。」が発生する場合、そのエラーが発生した箇所に閉じ忘れがある場合は改修も容易ですが、そうでない場合はカーソルを閉じ忘れている箇所を特定するのに四苦八苦することも多いです。

単純にソースを逆に追っていけばいつかはカーソルを閉じ忘れている箇所にいつかはたどり着くはずですが、あちらこちらで大量のSQLを実行しているような複雑なアプリケーションではたどり着くまでにかなりの時間を費やす可能性もあります。

このようなときには、V$OPEN_CURSORビューを活用すればカーソルを閉じ忘れている箇所をすばやく特定できる可能性があります。


例えば、単純にどのセッションでどんなSQL文のカーソルがオープンされているかを調べるなら以下のようなSELECT文を実行すればOKです。

SQL> SELECT SID, USER_NAME, SQL_TEXT FROM V$OPEN_CURSOR;

       SID USER_NAME  SQL_TEXT
---------- ---------- ------------------------------------------------------------
        23 SCOTT      SELECT D.DEPTNO,D.DNAME,AVG(E.SAL) FROM EMP E INNER JOIN DEP
        21 SCOTT      SELECT ENAME FROM EMP WHERE EMPNO = :1
        21 SCOTT      SELECT * FROM EMP
         .
         .
         .

似たようなSQL文のカーソルが大量にオープンされていれば、そのSQL文を実行している箇所でカーソルを閉じ忘れている可能性が高いと考えられます。


また、最大オープン・カーソル数を超えるような場合、繰り返し処理される部分で発生する可能性が高いため、以下のようなSELECT文を実行し、同じSQL文のカーソルが大量にオープンされていないかどうかを調べてみたほうが手っ取り早いかもしれません。

SQL> SELECT OC.SID, OC.USER_NAME, ST.SQL_TEXT, OC.NUM_CURSORS
  2     FROM V$SQL ST
  3     INNER JOIN (
  4             SELECT SID, USER_NAME, ADDRESS, HASH_VALUE, COUNT(*) NUM_CURSORS
  5                     FROM V$OPEN_CURSOR
  6                     GROUP BY SID, USER_NAME, ADDRESS, HASH_VALUE
  7                     HAVING COUNT(*) > 1
  8     ) OC
  9             ON OC.ADDRESS = ST.ADDRESS
 10                     AND OC.HASH_VALUE = ST.HASH_VALUE
 11     ORDER BY OC.SID;

       SID USER_NAME  SQL_TEXT                                 NUM_CURSORS
---------- ---------- ---------------------------------------- -----------
        21 SCOTT      SELECT E.ENAME, D.DNAME FROM EMP E INNE         286
                      R JOIN DEPT D ON E.DEPTNO = D.DEPTNO WHE           2
                      RE E.EMPNO = :1
        21 SCOTT      SELECT ENAME FROM EMP WHERE EMPNO = :1             2
        22 SCOTT      SELECT * FROM EMP                                  2
        23 SCOTT      SELECT D.DEPTNO,D.DNAME,AVG(E.SAL) FROM            2
                      EMP E INNER JOIN DEPT D ON E.DEPTNO = D
                      .DEPTNO WHERE D.DEPTNO = :1
         .
         .
         .

例えば、上記の例の場合、一番上のカーソルが286回もオープンされていますので、そのSQL文を実行している箇所でカーソルを閉じ忘れている可能性が高いと考えられます。



【関連エントリ】
[Oracle] ORA-01000エラーの回避方法 2004/07/04
[Oracle] ORA-01000エラーの原因特定のためにV$OPEN_CURSORを利用する 2006/10/03