코린이의 기록

[SQL Exeption] ORA-01000 open cursor 에러 본문

Database/Oracle

[SQL Exeption] ORA-01000 open cursor 에러

코린이예요 2018. 5. 3. 10:31
반응형

이슈 발생 

접속 SQL Exception으로인해 로그인이 안되는 상황 


Open Cursor?
-- v$open_cursor
에서 session cursor수를 조회하여 어떤 쿼리가 cursor 잡고 있는지 확인

1
2
3
4
5
select sid, count(sid) cursor
from v$open_cursor
where user_name = '[user_name]'
group by sid
order by cursor desc;
cs



-- 쿼리별로 sid 개수를 확인 - SQL문당 사용하는 커서수

1
2
3
4
5
6
select sql_text, count(sid) cnt
from v$open_cursor
where user_name = '[user_name]'
group by sql_text
order by cnt desc;
 
cs


-- sid serial 확인 (문제가 되는 쿼리의 sid 통해 세션확인)

1
2
select sid, serial#, username
from v$session;
cs

--결과값의 sid username 파악한 문제가 되는 session있다면 죽여라

1
alter system kill session 'sid,serial#';
cs



커서 올리기

open_cursors 설정

1
ALTER SYSTEM SET open_cursors=1000;
cs

maximum open cursor  확인

1
show parameter open_cursors;
cs


원인 분석 1

ibatis 프레임 워크를 사용하므로 connection 이나 preparedstatement 직접 열고 닫을 일은 없으므로 소스내에서 close하지 않은 부분을 찾는 해결방법을 의미가 없다

참고로 ibatis 모든 쿼리를 prepared statement 실행시킨다. 기본적인 statement pool 제공한다. (JDBC3.0 스펙에 해당됨)

원인 분석 2
statement pooling
JDBC 3.0 정의된 명세다. JDBC 드라이버가 3.0 명세를 지원하지 않으면 사용할 없는 기능이다. 하지만 JDBC 2.0 명세만 지원하는 JDBC 드라이버를 사용할 때도 커넥션 풀로 Commons DBCP 사용하고 있다면 poolPreparedStatements 옵션을 true 설정해서 Commons DBCP 커넥션 풀뿐만 아니라 statement pool로도 사용할 있다이때는 반드시 maxOpenPreparedStatements 옵션을 같이 사용해 커넥션당 풀링할 PreparedStatement 적절한 개수를 설정해야 한다. 그렇지 않으면 런타임에서 메모리 부족(out of memory) 오류 등이 발생할 있다.
maxOpenPreparedStatements
값은 문제가 발생지 않도록 50 정도로 작게 설정한 데이터베이스 관리자의 도움을 얻어 PreparedStatement 캐시 적중률(hit ratio) 관찰한 조정하기를 권장한다. 여기서 설정한 PreparedStatement 개수는 개별 커넥션마다 할당된다. 커넥션 풀에 10개의 커넥션이 있을  maxOpenPreparedStatements = 50이라면  10 x 50 = 500개의 PreparedStatement 캐시에 저장된다. 절대 BasicDataSource 클래스에 설정되는 개수가 아니다
아래 connection pool 대한 자세한 설명이 있음

http://d2.naver.com/helloworld/5102792


Parameter

 Default

 Description

 poolPreparedStatements

 false

 Enable prepared statement pooling for this pool

 maxOpenPreparedStatements

 unlimited

 The maximum number of open statements that can be allocated from the statement pool at the same time, or negative for no limit.


This component has also the ability to pool PreparedStatements. When enabled a statement pool will be created for each Connection and PreparedStatements created by one of the following methods will be pooled:
public PreparedStatement prepareStatement(String sql)
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)


NOTE - Make sure your connection has some resources left for the other statements. Pooling PreparedStatements may keep their cursors open in the database, causing a connection to run out of cursors, especially if maxOpenPreparedStatements is left at the default (unlimited) and an application opens a large number of different PreparedStatements per connection. To avoid this problem, maxOpenPreparedStatements should be set to a value less than the maximum number of cursors that can be open on a Connection.

https://commons.apache.org/proper/commons-dbcp/configuration.html

 
결론.
현재 프로젝트 소스 설정파일에 보면 poolPreapredStatements true 설정되어있다. 커서가 열려있는 상태인데, 이때 maxOpenPreparedStatements라는 값을 설정해주지 않으면 default unlimited값이 된다.
따라서 대량으로 sql문을 수행하는 동작을 경우 커서가 다량으로 열리고 닫히지 않은 상태가 되므로 관련 Exception 발생하게 된다. 따라서 해결방법은 poolPreparedStatemets 값을 false 설정해주거나, true 설정해줄 경우 maxOpenPreparedStatements값을 설정해주어야 한다.
*
문제는 maxOpenPreparedStatements값을 어느정도로 설정해주어야 적절한지 모르겠음..

 

반응형

'Database > Oracle' 카테고리의 다른 글

oracle developer 유용한 단축키  (0) 2022.12.01
[Oracle] linux에서 oracle 접속  (0) 2018.07.02
Comments