얼마전 프로젝에서 커넥션 릭으로 인해 많은 장애가 있었습니다.
아래 내용이 도움이 될 수 있겠습니다.
===================================================================================
최근문서수정일자: 2001.10.31
1. JDBC로 동시에 연결할 수 있는 java.sql.Connection 수
E:\temp> type DbMaxConnTest.java
import java.util.*;
import java.sql.*;
public class DbMaxConnTest
{
public static int MAX=10000;
public static void main(String[] args) throws Exception {
Class.forName(“oracle.jdbc.driver.OracleDriver”);
Vector conns = new Vector();
try {
for(int i=0 ; i< MAX; i++) {
Connection conn = DriverManager.getConnection(
“jdbc:oracle:thin:@localhost:1521:ORA8i”,
“scott”, “tiger”);
conns.addElement(conn);
System.out.println((i+1) + “-th connected”);
}
}
catch(Exception e){
e.printStackTrace();
}
finally {
Enumeration enum = conns.elements();
while(enum.hasMoreElements()){
Connection conn = (Connection)enum.nextElement();
try { conn.close();}catch(Exception e){}
}
}
}
}
E:\temp>set classpath=.;c:\jdk1.1.8\lib\classes.zip;e:\downloads\jdbc\classe
s111_01.zip
E:\temp>javac DbMaxConnTest.java
E:\temp>java DbMaxConnTest
1-th connected
2-th connected
3-th connected
……
44-th connected
45-th connected
46-th connected
47-th connected
java.sql.SQLException: ORA-00020: maximum number of processes (59) exceeded
at java.lang.Throwable.<init>(Throwable.java:74)
at java.lang.Exception.<init>(Exception.java:38)
at java.sql.SQLException.<init>(SQLException.java:36)
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java)
at oracle.jdbc.ttc7.TTIoer.processError(TTIoer.java)
at oracle.jdbc.ttc7.O3log.receive1st(O3log.java)
at oracle.jdbc.ttc7.TTC7Protocol.logon(TTC7Protocol.java)
at oracle.jdbc.driver.OracleConnection.<init>(OracleConnection.java)
at oracle.jdbc.driver.OracleDriver.getConnectionInstance(OracleDriver.ja
va)
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java)
at java.sql.DriverManager.getConnection(Compiled Code)
at java.sql.DriverManager.getConnection(DriverManager.java:119)
at DbMaxConnTest.main(Compiled Code)
1.1 Oracle
Oracle 에서 위에서 처럼 최대로 동시에 Open 할 수 있는 java.sql.Connection 수는
(저의 NT용 Personal Oracle 8.1.5 의 경우) E:\Oracle\ADMIN\ORA8i\pfile\init.ora
에서 아래의 파라메터를 수정함으로써 가능합니다.
………
processes = 59 # INITIAL
# processes = 50 # SMALL
# processes = 100 # MEDIUM
# processes = 200 # LARGE
………
이 파일은 통상 init<SID>.ora 파일이라는 SID 구성파일에서 수정합니다.
NOTE: 왜 Max값은 59 인데, 47까지만 연결되는 것인지는 저두 모르겠습니다. 수치를
올려도 꼭 12개씩의 차이가 생기는 군요…
—————————————
제목 Re: JSN:Connection/Statement 최대 동시 Open 수
보낸날짜 Mon, 23 Oct 2000 20:56:55 KST
보낸이 “CHOULGU KANG” <cgkang@lgeds.lg.co.kr>
받는이 “javaservice@hanmail.net” <javaservice@hanmail.net>
INIT파일에 정의해 놓은 DB 프로세스수를 전체를 사용할 수 없는 이유는 오라클
백그라운드 프로세스 등이 사용하는 수때문입니다.
좋은 하루 되시길 바랍니다. 강철구.
—————————————
1.2 IBM UDB DB2
대부분의 DB가 이와 유사한 파라메터를 제공할 것입니다.
예를 들어 IBM UDB DB2 의 경우는 다음과 같은 방식으로 이 수치를 바꿀 수 있습니다.
# su – db2inst1
# db2 get dbm cfg | grep MAXAGENTS
기존 에이전트의 최대 수 (MAXAGENTS) = 200
# db2 update dbm cfg using maxagents <number>
# db2 get db cfg for <database_name> | grep MAXAPPLS
실행 중인 프로그램의 최대 수 (MAXAPPLS) = 100
# db2 update db cfg for <database_name> using maxappls <mumber>
2. 하나의 Connection 에서 동시에 생성될 수 있는 Statement 의 수
E:\temp> type DbMaxStmtTest.java
import java.util.*;
import java.sql.*;
public class DbMaxStmtTest
{
public static int MAX=10000;
public static void main(String[] args) throws Exception {
Class.forName(“oracle.jdbc.driver.OracleDriver”);
Connection conn = DriverManager.getConnection(
“jdbc:oracle:thin:@localhost:1521:ORA8i”,
“scott”, “tiger”);
Vector stmts = new Vector();
try {
for(int i=0 ; i< MAX; i++) {
Statement stmt = conn.createStatement();
stmts.addElement(stmt);
System.out.println((i+1) + “-th statement created”);
}
}
catch(Exception e){
e.printStackTrace();
}
finally {
Enumeration enum = stmts.elements();
while(enum.hasMoreElements()){
Statement stmt = (Statement)enum.nextElement();
try { stmt.close();}catch(Exception e){}
}
try { conn.close();}catch(Exception e){}
}
}
}
E:\temp> javac DbMaxStmtTest.java
E:\temp> java DbMaxStmtTest
1-th statement created
2-th statement created
3-th statement created
….
48-th statement created
49-th statement created
50-th statement created
java.sql.SQLException: ORA-01000: 최대 열기 커서 수를 초과했습니다
(maximum open cursors exceeded)
at java.lang.Throwable.<init>(Throwable.java:74)
at java.lang.Exception.<init>(Exception.java:38)
at java.sql.SQLException.<init>(SQLException.java:36)
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java)
at oracle.jdbc.ttc7.TTIoer.processError(TTIoer.java)
at oracle.jdbc.ttc7.Oopen.receive(Compiled Code)
at oracle.jdbc.ttc7.TTC7Protocol.open(TTC7Protocol.java)
at oracle.jdbc.driver.OracleStatement.<init>(OracleStatement.java)
at oracle.jdbc.driver.OracleConnection.createStatement(OracleConnection.
java)
at DbMaxStmtTest.main(Compiled Code)
2.1 Oracle
이 처럼, 한 java.sql.Connection 에서 동시에 생성할 수 있는 statement 의 수는
Oracle의 경우 Oracle SID 구성파일에서 아래의 파라메터를 추가로 넣어줌으로써
변경할 수 있습니다.
…..
# OPEN_CURSORS=50 # Default
OPEN_CURSORS=100
…..
NOTE:
Error Message: “ORA-01000: maximum open cursors exceeded”
The number of cursors one client can open at a time on a connection is limited
(50 is the default value). You do need to explicitly close the statement, by
using the method stmt.close() in order to close and freeup the cursors.
If you dont close these cursors explicitly, you will get this error eventually.
Simply increasing the “OPEN_CURSORS” limit can help you avoid the problem for
a while, but that just hides the problem, not solve it. It is your responsibilty
to explicitly close out cursors that you no longer need.
NOTE: 2001.10.31
Oracle 의 경우, 현재 열려진 총 Statement의 개수를 보는 방법이 있습니다.
——————————————-
select sid, count(*) cnt from v$open_cursor
where user_name = ‘username’
group by sid
order by cnt desc
——————————————-
(도움주신분: 정헌식 <vblove@buttle.co.kr>)
2.2 IBM UDB DB2
IBM UDB DB2 의 경우는 Oracle 의 “open_cursors” 와 같은 개념의 파라메터가
없습니다. 시스템의 메모리가 허용하는 한 끝까지 죽을 때 까지 생성시키는
군요…
아래와 같은 테스트에서 1463 개의 statement 를 만들더니, 시스템이 벅벅느려지고
급기야 에러를 내고 마는 군요…..
시스템의 메모리에 따라 개수제한이 있을 뿐인 듯 합니다.
E:\temp> type Db2MaxStmtTest.java
import java.util.*;
import java.sql.*;
public class Db2MaxStmtTest
{
public static int MAX=10000;
public static void main(String[] args) throws Exception {
Class.forName(“COM.ibm.db2.jdbc.app.DB2Driver”).newInstance();
Connection conn = DriverManager.getConnection(
“jdbc:db2:was”, “db2admin”, “db2admin”);
Vector stmts = new Vector();
try {
for(int i=0 ; i< MAX; i++) {
Statement stmt = conn.createStatement();
stmts.addElement(stmt);
System.out.println((i+1) + “-th statement created”);
}
}
catch(Exception e){
e.printStackTrace();
}
finally {
Enumeration enum = stmts.elements();
while(enum.hasMoreElements()){
Statement stmt = (Statement)enum.nextElement();
try { stmt.close();}catch(Exception e){}
}
try { conn.close();}catch(Exception e){}
}
}
}
E:\temp> javac Db2MaxStmtTest.java
E:\temp> java Db2MaxStmtTest
1-th statement created
2-th statement created
3-th statement created
….
1461-th statement created
1462-th statement created
1463-th statement created
COM.ibm.db2.jdbc.DB2Exception: [IBM][JDBC 드라이버] CLI0601E 유효하지 않은 명령
문 핸들 또는 명령문이 닫혔습니다. SQLSTATE=S1000
at java.lang.Throwable.<init>(Throwable.java:74)
at java.lang.Exception.<init>(Exception.java:38)
at java.sql.SQLException.<init>(SQLException.java:36)
at COM.ibm.db2.jdbc.DB2Exception.<init>(DB2Exception.java:93)
at COM.ibm.db2.jdbc.app.SQLExceptionGenerator.throw_SQLException(SQLExce
ptionGenerator.java:278)
at COM.ibm.db2.jdbc.app.SQLExceptionGenerator.throw_SQLException(SQLExce
ptionGenerator.java:187)
at COM.ibm.db2.jdbc.app.SQLExceptionGenerator.check_return_code(SQLExcep
tionGenerator.java:426)
at COM.ibm.db2.jdbc.app.DB2Statement.<init>(Compiled Code)
at COM.ibm.db2.jdbc.app.DB2Statement.<init>(Compiled Code)
at COM.ibm.db2.jdbc.app.DB2Connection.createStatement(Compiled Code)
at Db2MaxStmtTest.main(Compiled Code)
위 에러를 혹 보신 적 있나요? 엉뚱한 다른 부분을 의심하지 않으셨던가요?
만약, 어플리케이션 서버 프로세스가 점유하고 있는 메모리사이즈가 계속적으로
증가하면서, 급기야 위와 같은 에러를 내는 경우를 보신 적 있나요?
DB2 에서는 Oracle 처럼 “ORA-01000: maximum open cursors exceeded” 라는
SQLException 메세지가 없습니다. 또한 제한이 없기 때문에, 문제를 야기하여
시스템이 다운되기 전까진 아무도 관심도 가져주지 않고, 설령 메모리 문제로
인해 다운되면 엉뚱한 곳을 의심하게 됩니다.
이제 위의 에러메세지를 만나면, java.sql.Statement 를 반드시 finally 절에서 꼭
close() 하세요….
PS: 이 글을 읽으면서 “그래서 그게 어쨌다구.. 시큰둥…” 하고 계신다면,
아직 아래글을 탐독하지 않으신게 분명합니다.
“서블렛 + JDBC 연동시 코딩 고려사항 -제1탄-“
http://www.javaservice.net/~java/bbs/read.cgi?m=devtip&b=servlet&c=r_p&n=968185187
——————————————————-
본 문서는 자유롭게 배포/복사 할 수 있으나 반드시
이 문서의 저자에 대한 언급을 삭제하시면 안됩니다
================================================
자바서비스넷 이원영
E-mail: javaservice@hanmail.net
PCS:019-310-7324
================================================