현재글)
다음글)
내가 담당하고 있는 서비스에서 간헐적으로 DB Connection이 끊기는 현상이 발생했다.
처음에는 단순히 DB Connection Pool 의 개수가 모자른가? 라고 생각했었지만, 생각치도 못했던 여러 문제를 접하였고, 그에 대한 오답노트를 적어보려고 한다.
📢 환경
- Ubuntu 18.04.5 LTS
- SpringBoot 2.5.12
- MySQL 5.7.28DB에서 데이터를 꺼내기 위해 커넥션을 사용하려고 하는데, 설정된 timeout 시간까지 커넥션 풀에서 사용 가능한 커넥션을 못찾아 에러가 발생하였다. stack trace 를 보면 아래와 같다.
DataAccessResourceFailureException
Unable to acquire JDBC Connection; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
JDBCConnectionException
Unable to acquire JDBC Connection
SQLTransientConnectionException
HikariPool-1 - Connection is not available, request timed out after 15016ms.
SQLNonTransientConnectionException
No operations allowed after connection closed.
...처음 저 에러를 접했을때, 오잉? Connection Pool Size 가 작은가?? 해당 서버에 요청이 많아졌나..?? 라고 생각했고, 단순하게 Pool Size만 늘리는 조치를 취했지만… 해당 에러는 계속 발생했다.
그래서 열심히 구글에 검색을 해보니, 아래와 같은 키워드를 발견하였다.
만약, wait_time < max-lifetime 일 경우 커넥션 풀에 존재하는 모든 커넥션이 유효한 커넥션이 아닐 수도 있게된다.
왜냐면, wait_time 시간이 지난 커넥션들은 DB서버에서 먼저 연결을 끊기 때문이다.
때문에 풀은 이걸 모르고 계속 가지고 있다가 어플리케이션에서 요청하면 유효하지 않은 커넥션을 계속 주게 될 수도 있다는거다.
MySQL의 wait_timeout 을 확인해보니 기본값인 8시간이다.
show global variables like 'wait_timeout';오잉??
application.yaml 파일에도 max-lifetime을 설정하지 않았는데.. 그럼 기본값이니 30분일 텐데.. 충분히 작은데..?
그럼 max-lifetime을 10분으로 설정해서 max-lifetime에 새로 연결을 맺는지 한번 확인해보자.
참고) Hikari Pool 로그를 보기 위해 logback-spring.xml 를 아래와 같이 설정해야 한다. (logback 기준)
connection adder 스레드로 커넥션이 풀에 추가가 되었고, 00:05분에(10분 후) 해당 커넥션을 사용하지 않아 connection closer 스레드로 Closing 되었다.아니 그럼 대체 뭐가 문제인 것인가?? 뷁!
다음 페이지로 > Unable to acquire JDBC Connection(DHCP lease lost) 에러 오답노트2