반응형

다음과 같은 에러가 나타날 때 처리
com.enrise.framework.exception.DSSqlException: Communications link failure due to underlying exception:

** BEGIN NESTED EXCEPTION **

java.net.SocketException
MESSAGE: Software caused connection abort: socket write error

STACKTRACE:

java.net.SocketException: Software caused connection abort: socket write error
 at java.net.SocketOutputStream.socketWrite0(Native Method)
 at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
 at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
 at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
 at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
 at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:2744)
 at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1612)
 at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1723)
 at com.mysql.jdbc.Connection.execSQL(Connection.java:3283)
 at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1332)
 at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1467)
 at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:93)
 at com.enrise.framework.db.query.LoggableStatement.executeQuery(LoggableStatement.java:231)
 at com.enrise.framework.db.query.QueryManager.executeQueryOne(QueryManager.java:241)
 at com.enrise.framework.db.query.QueryManager.executeQueryOne(QueryManager.java:227)
 at com.enrise.ds.am.dao.AmUserDAO.getUserByUserID(AmUserDAO.java:213)
 at com.enrise.ds.am.business.AmUserBusiness.getUserByUserID(AmUserBusiness.java:156)
 at com.enrise.ds.common.command.CoLoginCommand.execute(CoLoginCommand.java:224)
 at com.enrise.ds.common.servlet.HTTPServices.doPost(HTTPServices.java:115)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

......


해결 -> http://amitcodes.wordpress.com/2008/07/26/16/
위에 링크를 한 블로거의 설명 및 해결 방법 이다.
Cause:
 MySQL server has a default timeout period after which it terminates the idle connections. This period is 8 hours by default. Now heres what happens. The dbcp creates a set of connections to database when the servlet container / application server starts up. If the connections are not used for the tinmeout period, the MySQL server assumes these to be dead connections and terminates them. The dbcp, however, is unaware of the fact that the connections have been terminated. So when a connection is demended from the connection-pool, these dead connections are returned and when a call is made on these dead connections  *BOOM*  you the java.net.SocketException: Broken pipe exception. Ok  so whats the fix ??

Fix: If only the connection pool could check if the the connection it is about to return is live or not, the porblem is fixed. This can be done in apache-common-dbcp (I know this one coz I used it, please look into documentation of the connection-pool you are using). Heres how you do it: You add the following properties to dbcp configuration.

·        validationQuery=SELECT 1

·        testOnBorrow=true

And that does the trick.

How it works:

·        Before returning the connection from pool to the application, dbcp runs the SELECT 1  query on the connection to see it it is still live. Thats the job of validationQuery.

·        As for testOnBorrow, you tell dbcp to perform the check before returning the connection to application.

For more details refer to the apache-common-dbcp configuration manual hereThe apache-commons-dbcp config:

view source

print?

01

<Resource   name="jdbc/cooldatabase"

02

            description="Strandls.com license database"

03

            auth="Container"

04

            type="javax.sql.DataSource"

05

            factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"

06

            driverClassName="com.mysql.jdbc.Driver"

07

            url="jdbc:mysql://localhost:3306/cooldatabase?autoReconnect=true"

08

            username="cooluser"

09

            password="coolpassword"

10

            initialSize="0"

11

            maxActive="20"

12

            maxIdle="10"

13

            minIdle="0"

14

            maxWait="-1"

15

            validationQuery="SELECT 1"

16

            testOnBorrow="true"

17

            poolPreparedStatements="true"

18

            removeAbandoned="true"

19

            removeAbandonedTimeout="60"

20

            logAbandoned="true"/>

The complete stacktrace:

[ERROR] 12:27 (JDBCExceptionReporter.java:logExceptions:78)Communications link failure due to underlying exception:

 

** BEGIN NESTED EXCEPTION **

 

java.net.SocketExceptionMESSAGE: Broken pipe

 

STACKTRACE:

java.net.SocketException: Broken pipeat

java.net.SocketOutputStream.socketWrite0(Native Method)

at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)

at java.net.SocketOutputStream.write(SocketOutputStream.java:136)

at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)

at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)

at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:2689)

at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:2618)

at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1551).....

 

 

--------------------------------------------------------------------------------------------------------------------------

 요약 하자면

원인: MySQL은 디폴트 타임아웃 값을 가지고 있다만약 커넥션이 생성되고이 타임아웃 기간이 지날 동안 사용되지 않는다면 이 커넥션은 끊긴 것으로 간주하고 커넥션을 종료한다하지만 dbcp는 커넥션이 끊어졌음을 알아채지 못하고커넥션 요청이 있을 때 연결이 끊긴 커넥션을 돌려준다그래서 에러가 발생한다.

 

수정: DBCP configuration 에 다음 사항을 추가한다.

·        validationQuery=SELECT 1

·        testOnBorrow=true

·        url="jdbc:mysql://localhost:3306/dbPoolName?autoReconnect=true

동작하는 방식

l  어플리케이션에 커넥션을 리턴하기 전에 dbcp는 “SELECT 1”쿼리를 실행해서 해당 커넥션이 살아있는지 확인한다이 작업이 ‘validationQuery’ 이다.

l  testOnBorrow 를 설정함으로써 커넥션을 어플리케이션에 돌려주기 전에 dbcp가 체크하도록 한다.

 

 

 < 설 명 >
'autoReconnect'옵션을 주게 되면, 커넥션에 문제가 있을 경우 다시 접속하게 된다.
그러나, 이 경우에도 끊어진 후 처음 한번의 시도는 실패가 나게 된다(이때 문제가 있다는것을 알게 되는 것이므로..).
이때는 추가적인 DBCP옵션인 'validationQuery'값의 설정으로 해결 가능하다.
validationQuery="select 1" => MySQL의 경우
validationQuery="select 1 from dual" => Oracle의 경우


maxActive 커넥션 풀이 제공할 최대 커넥션 개수 
maxIdle 사용되지 않고 풀에 저장될 수 있는 최대 커넥션 개수. 음수일 경우 제한이 없다. 
maxWait whenExhaustedAction 속성의 값이 1일 때 사용되는 대기 시간. 단위는 1/1000초이며, 0 보다 작을 경우 무한히 대기한다. 
testOnBorrow true일 경우 커넥션 풀에서 커넥션을 가져올 때 커넥션이 유효한지의 여부를 검사한다. 
testWhileIdle true일 경우 비활성화 커넥션을 추출할 때 커넥션이 유효한지의 여부를 검사해서 유효하지 않은 커넥션은 풀에서 제거한다. 
timeBetweenEvctionRunsMillis 사용되지 않은 커넥션을 추출하는 쓰레드의 실행 주기를 지정한다. 양수가 아닐 경우 실행되지 않는다. 단위는 1/1000 초이다. 
minEvictableIdleTimeMillis 사용되지 않는 커넥션을 추출할 때 이 속성에서 지정한 시간 이상 비활성화 상태인 커넥션만 추출한다. 양수가 아닌 경우 비활성화된 시간으로는 풀에서 제거되지 않는다. 시간 단위는 1/1000초이다. 



출처 : 

http://invincure.tistory.com/entry/%EC%BB%A4%EB%84%A5%EC%85%98-%ED%92%80-%EC%9D%B4%EC%9A%A9%EC%8B%9C-DB-%EC%BB%A4%EB%84%A5%EC%85%98-%EC%97%90%EB%9F%AC

'JAVA > Spring' 카테고리의 다른 글

java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener  (0) 2016.06.02
Spring log4j SQL 직관적으로 보기  (0) 2016.06.02
[Spring] MVC 예제  (0) 2014.11.18
[Spring] MCV  (0) 2014.11.18
[Spring] AOP  (0) 2014.11.18

+ Recent posts