単純にソースを逆に追っていけばいつかはカーソルを閉じ忘れている箇所にいつかはたどり着くはずですが、あちらこちらで大量の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