tomcat-jdbc로 MySQL에 연결한 경우 “java.net.SocketException: Broken pipe” 에러가 발생하는 경우를 가끔 볼 수 있다. 대부분의 경우 connection idle time이 MySQL에 설정된 wait_timeout을 지나서 DB에서 연결을 끊은 것이다. 이를 방지하려면 connection이 일정 기간동안 사용되지 않으면 close되도록 설정하거나 connection 대여시에 connection을 체크하도록 하면 된다.
설정 1 – 일정 기간동안 사용되지 않으면 connection을 테스트
validationQuery=”SELECT 1″
testWhileIdle=”true”
minEvictableIdleTimeMillis=”3600000″
timeBetweenEvictionRunsMillis=”60000″
(*) DB에 쿼리를 하기 때문에 이 때마다 DB의 session idle time이 갱신된다. 만약 connection이 이미 끊겼다면 에러가 발생할테고 해당 connection은 pool에서 제거된다.
(*) timeBetweenEvictionRunsMillis의 기본값은 5000 (5초)이고, minEvictableIdleTimeMillis의 기본값은 60000 (60초)이다. minEvictableIdleTimeMillis 값은 MySQL에 설정된 wait_timeout이나 방화벽에 설정된 session timeout 값보다 작아야 한다.
설정 2 – connection 대여 시 테스트
validationQuery=”SELECT 1″
testOnBorrow=”true”
(*) 매번 connection 대여 시 마다 체크하는 것은 아니다. 체크 한 connection은 validationInterval 기간 안에는 다시 체크하지 않는다. validationInterval의 기본값은 30000 (30초).
설정 3 – 일정 기간동안 사용되지 않으면 connection을 close
minIdle=”0″
설정 1을 사용한 JDBC Resource 설정 예
context.xml |
<?xml version=”1.0″ encoding=”UTF-8″?><Context>
<Resource name=”jdbc/testDB” auth=”Container” type=”javax.sql.DataSource” factory=”org.apache.tomcat.jdbc.pool.DataSourceFactory” driverClassName=”com.mysql.jdbc.Driver” url=”jdbc:mysql://localhost/smartconnect?useUnicode=true&characterEncoding=utf8″ username=”username” password=”password” initialSize=”10″ minIdle=”10″ maxIdle=”50″ maxActive=”50″ maxWait=”5000″ validationQuery=”SELECT 1″ validationInterval=”30000″ testWhileIdle=”true” /> </Context> |
tomcat-jdbc PoolCleaner 동작
PoolCleaner thread는 timeBetweenEvictionRunsMillis 만큼 sleep하다 idle/abandoned connection을 체크한다.
- removeAbandoned=”true”이면 abandoned connection 체크
- connection이 대여된 후 removeAbandonedTimeout (초, 기본값 60)안에 반납되지 않으면 connection을 pool에서 제거하고 close한다.
- pool의 idle connection 개수가 minIdle보다 크면 체크
- idle connection 개수가 minIdle이 될 때 까지 마지막 사용시간이 minEvictableIdleTimeMillis (기본값 60000)을 지난 idle connection을 찾아 pool에서 제거하고 close한다.
- testWhileIdle=”true”이면 idle connection들에 대해 validation 테스트
- 전체 idle connection에 대해 validationQuery에 설정된 SQL을 수행해서 Exception이 발생하면 pool에서 제거하고 close한다.
MySQL wait_time 설정값 확인 방법 (단위: 초)
mysql>select @@global.wait_timeout;
+———————–+
| @@global.wait_timeout |
+———————–+
| 28800 |
+———————–+
1 row in set (0.00 sec)
[출처] Tomcat7 tomcat-jdbc 설정 – Broken pipe 에러 회피|
[[추가]]
jdbc connection string에 하기와 같이 autoconnection option을 추가 해줘도 된다.
즉 이 옵션이 켜 있으면 끊긴 커넥션을 자동으로 재 접속 처리 한다.
문제는.. 트랜잭션이 걸려 있을 경우 잘 못 하면 트랜잭션이 꼬일 수 있으므로
복잡한 작업을 하는 경우에는 이 옵션을 꺼 놓는게 좋다..
잘 못된 데이서 생성 보다는 오류 메시지 표출이 나으니깐..
Cannot get a connection, pool error Timeout waiting for idle object (Tomcat forum at JavaRanch)
|
첨언:: 각 옵션을 복합적으로 사용할때는 &를 써야 하는데 이게 오류를 일으킨다. 그래서
& 로 바꿔서 각 옵셕을 이어주면 된다.
?characterEncoding=UTF-8&autoConnect=true