본문 바로가기
Programming/Spring

Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure 출처: http://blumorning0227.tistory.com/87 [파란아침]

by 막이 2018. 11. 9.

회사 내부 관리앱 서버가 계속 아래와 같은 에러를 뱉어서 검색해보니 커넥션이 끊긴 상태에서 쿼리를 보내서

에러가 난다고함  에러 후 새로고침하면 잘돌아가서 방치하다가 이제서야 고침.......ㅎㅎ 


스프링부트 1.5.8 버전으로 만든 프로젝트로 


application.properties에


#maintain db connect

spring.datasource.tomcat.testOnBorrow=true        

spring.datasource.tomcat.validationQuery=SELECT 1 


이렇게 추가해주었다. 



다른 스프링에는

<!-- MySQL -->

<bean id="dataSource-Mysql" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">

<property name="driverClassName" value="${Globals.DriverClassName}"/>

<property name="url" value="${Globals.Url}" />

<property name="username" value="${Globals.UserName}"/>

<property name="password" value="${Globals.Password}"/>

<property name="maxTotal" value="100" />

<property name="maxIdle" value="10" />

<property name="maxWaitMillis" value="10000" />

<property name="minEvictableIdleTimeMillis" value="60000" />

<property name="removeAbandonedTimeout" value="300" />

<property name="removeAbandonedOnMaintenance" value="true"/>

<property name="removeAbandonedOnBorrow" value="true"/>

<property name="logAbandoned" value="true"/>

<property name="timeBetweenEvictionRunsMillis" value="60000"/>

<property name="validationQuery" value="select 1" />

<property name="testWhileIdle" value="true" />

</bean>


이렇게 설정되어있었음. 

당연한듯 갖다 쓰기만해서 저게 뭘 의미하는지도 몰랐넹 ㅜㅜ 





<!-- DB Pool이 생성이 되더라고 특정 시간 호출되지 않으면 DBMS 설정에 따라 연결을 끊어질 때

이 경우 DBCP를 사용하셨다면.. 다음과 같은 설정을 추가하시면 연결을 유지시켜 줍니다. -->

<!--

<property name="validationQuery" value="select 1 from dual" />

<property name="testWhileIdle" value="true" />

<property name="timeBetweenEvictionRunsMillis" value="60000" /> -->  <!-- 1분 -->


<!-- DBCP가 아닌 WAS의 DataSource를 사용하시는 경우도 WAS별로 동일한 설정을 하실 수 있습니다.

(WAS별 구체적인 설정은 WAS document 확인) -->


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



### Error querying database.  Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

 

The last packet successfully received from the server was 353,678,680 milliseconds ago.  The last packet sent successfully to the server was 1 milliseconds ago.

### The error may exist in sql/cuMonitorSQL.xml

### The error may involve cuMonitor.selectCurrentCuInfo

### The error occurred while executing a query

### SQL: [쿼리내용]

### Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

 

The last packet successfully received from the server was 353,678,680 milliseconds ago.  The last packet sent successfully to the server was 1 milliseconds ago.

; SQL []; Communications link failure

 

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

 

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

n  
validationQuery=SELECT 1
n  testOnBorrow=true
n  JDBC URL autoReconnect=true 추가


<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"

   destroy-method="close" p:driverClassName="${jdbc.driver}" p:url="${jdbc.db_admindb.url}"p:username="${jdbc.username}" p:password="${jdbc.password}" p:validationQuery="SELECT 1"p:testOnBorrow="true"/>

 

jdbc.db_gamedb.url=jdbc:mysql://[..URL..]?noAccessToProcedureBodies=true&useInformationSchema=true&autoReconnect=true

 

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

  • validationQuery="select 1" => MySQL의 경우
  • validationQuery="select 1 from dual" => Oracle의 경우

어플리케이션에 커넥션을 리턴하기 전에 dbcp는 “SELECT 1”쿼리를 실행해서 해당 커넥션이 살아있는지 확인한다. 이 작업이 ‘validationQuery’ 이다. 
testOnBorrow 를 설정함으로써 커넥션을 어플리케이션에 돌려주기 전에 dbcp가 체크하도록 한다.

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



출처: http://blumorning0227.tistory.com/87 [파란아침]