Aurora MySQL의 숨겨진 연결 종료 동작, HikariCP 로그 추적기
HikariCP에서 "Failed to validate connection" WARN 로그가 분당 다수 발생하며 연결 유효성 검증 문제가 시작됨
표준 MySQL 모델 기반의 가설 검증 결과, wait_timeout과 interactive_timeout의 비표준 동작이 원인으로 지목됨
Aurora MySQL의 dual timeout 메커니즘으로 인해 발생하며, interactive_timeout 값 조정으로 해결함
표준 MySQL과 Aurora MySQL의 Idle Close 동작 차이
표준 MySQL은 연결 시 CLIENT_INTERACTIVE 플래그에 따라 `wait_timeout` 또는 `interactive_timeout` 중 하나만 세션 타임아웃으로 사용합니다. 반면 Aurora MySQL은 두 타임아웃 값 중 작은 값을 기준으로 모든 idle 세션을 종료시키는 dual timeout 메커니즘을 사용합니다. 이는 Aurora가 제한된 수의 worker thread를 공유하는 thread-pool 아키텍처를 사용하기 때문이며, 각 연결이 특정 thread에 고정되지 않아 표준 MySQL의 자연스러운 idle 종료 판정 방식 적용이 어렵기 때문입니다. 따라서 Aurora 환경에서는 `wait_timeout`만 늘리는 것으로는 부족하며, `interactive_timeout` 값의 동시 조정이 필수적입니다.
HikariCP "Failed to validate connection" 로그의 근본 원인
HikariCP의 `keepaliveTime`(30초) 설정에도 불구하고 "Failed to validate connection" 로그가 발생한 이유는 Aurora MySQL의 effective idle timeout(예: 20초)이 `keepaliveTime`보다 짧았기 때문입니다. Aurora는 `min(wait_timeout, interactive_timeout)`으로 계산된 짧은 idle 시간 내에 연결을 종료시키고, HikariCP의 keepalive ping 시점에는 이미 연결이 끊어진 상태였습니다. 이로 인해 연결 유효성 검증에 실패하며 "No operations allowed after connection closed" 오류가 발생했습니다. 근본적인 해결을 위해서는 Aurora의 idle timeout 값을 클라이언트의 keepalive 주기보다 길게 설정해야 합니다.
Aurora MySQL의 Thread-Pool 및 Monitor Thread 메커니즘
Aurora MySQL은 각 연결마다 OS 스레드를 할당하는 표준 MySQL과 달리, 제한된 수의 worker thread를 여러 연결이 공유하는 thread-pool 구조를 사용합니다. 이 구조는 CPU 코어 활용률을 높이지만, idle 연결을 감지하기 위해 별도의 모니터링 스레드가 필요합니다. 이 모니터링 스레드는 약 60초 주기로 `wait_timeout`과 `interactive_timeout` 중 작은 값을 기준으로 idle 연결을 검사하고 종료시킵니다. 이 메커니즘이 Aurora의 비표준 dual timeout 동작의 기술적 배경이며, 이로 인해 연결 유지 타이밍에 예측 불가능성이 발생할 수 있습니다.
HikariCP와 Aurora MySQL 연동 시 권장 설정 및 주의사항
Aurora MySQL 환경에서 HikariCP 사용 시, DB 파라미터 그룹의 `wait_timeout`과 `interactive_timeout` 값을 동일하게 설정하는 것이 혼란을 줄입니다. 두 값 중 작은 값이 실제 idle timeout으로 적용되므로, 이 값을 HikariCP의 `keepaliveTime` 및 `maxLifetime` 설정보다 충분히 길게 설정해야 합니다. 클라이언트 측 설정만으로는 Aurora의 서버 측 동작으로 인한 연결 문제를 해결할 수 없으므로, 서버 측 파라미터 조정이 근본적인 해결책임을 인지해야 합니다. 신규 클러스터 연동 시에는 이 두 파라미터의 정합성을 반드시 확인해야 합니다.
비표준 동작 발견 시 디버깅 전략
표준 모델 기반의 가설이 실제 환경에서 부정될 때, 가정했던 모델 자체가 틀렸을 가능성을 염두에 두어야 합니다. 이번 사례처럼 "interactive_timeout 만 늘렸더니 문제가 해결되었다"는 실측 결과는 표준 모델과의 모순을 드러내는 강력한 단서가 됩니다. 가설이 부정될 때 그 이유를 깊이 파고들어 "왜 부정되었는가"를 추적하는 것이 다음 가설 수립에 결정적인 도움을 줍니다. 또한, 공식 문서에 명시되지 않은 동작이라도 외부 자료, 커뮤니티 보고, 벤더 지원 채널 등을 통해 교차 검증하여 기술적 이해를 넓히는 것이 중요합니다.