개발햄비

[버그해결]MySQL , Maria DB Connection을 잃어버리는 문제 해결 본문

개발/버그 해결 기록

[버그해결]MySQL , Maria DB Connection을 잃어버리는 문제 해결

개발햄 2019. 3. 27. 15:34

 

결합 테스트를 후 모든 게 정상이었던 시스템에 갑자기 Exception에러가 발생하였다.

 

org.springframework.dao.DataAccessResourceFailureException: could not execute query; nested exception is org.hibernate.exception.JDBCConnectionException: could not execute query

 

The last packet successfully received from the server was 35,986,917 milliseconds ago. The last packet sent successfully to the server was 22 milliseconds ago. at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at com.mysql.jdbc.Util.handleNewInstance(Util.java:411) at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1116)

 

com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception: 

*현장 보안 때문에 에러코드는 다른 홈페이지에서 카피해옴 

 

 위와 같이 JDBCConnectionException, CommunicationsException 에러가 발생하였다

 

이유를 찾아보니 Mysql 의 경우 기본적으로 8시간 안에 request가 오지 않으면 강제적으로 Connection을 닫아버리기 때문에

오래 방치해두고 request를 날리면 먹통이 되는 에러였다.

 

해결방법은 아래와 같다

DB접속 URL에 

url="jdbc:mysql://localhost:3306/test?autoReconnect=true" 또는 validationQuery="select 1"

을 설정해주면 된다.

 

하지만 autoReconnect 옵션은 쿼리를 수행한 다음 DB 세션에 문제가 있으면 단순히 SQLException 리턴 후 재접속 처리를 한다.

하지만 문제는 트랜잭션 구동 환경에서  수행 중이던 트랜잭션은 롤백이 되어야 하고, 남은 트랜잭션은 수행이 되지 않아야 되는데, autoReconnect 옵션은 이런 처리를 해주지 않기 때문이다.

 

문제를 막기 위해서 autoReconnect=true인 환경에서는 SQLException이 발생하는 경우에, 해당 트랜잭션이 더 이상 진행되지 않도록 App 단에서 직접 예외 처리를 해줘야 하고, MySQL 레퍼런스 매뉴얼에서도 autoRecoonect 옵션 사용은  권장하지 않고 있다.

 

Property Name

Definition

Default Value

Since Version

autoReconnect

Should the driver try to re-establish stale and/or dead connections? If enabled the driver will throw an exception for a queries issued on a stale or dead connection, which belong to the current transaction, but will attempt reconnect before the next query issued on the connection in a new transaction. The use of this feature is not recommended, because it has side effects related to session state and data consistency when applications don't handle SQLExceptions properly, and is only designed to be used when you are unable to configure your application to handle SQLExceptions resulting from dead and stale connections properly. Alternatively, investigate setting the MySQL server variable "wait_timeout" to some high value rather than the default of 8 hours.

false

1.1

트랜잭션을 사용하는 환경이라면 DB 세션의 재접속 처리는 JDBC의 autoReconnect 설정이 아닌

DBCP의 validationQuery="select 1"  기능을 사용하는 것이 적합하다.

 

java에서 DB를 사용하기 전에 해당 connection 이 정상적인지 검사를 하도록 하는 것이다. 이 옵션이 validationQuery 파라미터이다.

 

- MySQL

  • validationQuery="select 1"

 - 오라클의 경우

  • validationQuery="select 1 from dual"