DB

[MySQL] (연결최적화5️⃣) 커넥션 누수 원인 진단과 해결 전략

인생아 2025. 7. 18. 23:40
반응형

MySQL 애플리케이션에서 커넥션 누수(Connection Leak)는 가장 치명적인 성능 저하 요인 중 하나다.
커넥션이 제대로 반납되지 않으면 커넥션 풀이 점점 고갈되어 전체 시스템이 다운될 수 있다.

🧨 커넥션 누수란?

커넥션 누수는 획득한 DB 연결을 close()하지 않아 커넥션 풀이 줄지 않고 계속 고갈되는 현상이다.
결국 새로운 연결을 못 얻어 Timeout waiting for connection 예외가 발생하게 된다.

대표적인 커넥션 누수 증상

  • CPU는 낮은데 DB 연결이 계속 증가
  • HikariCP에서 connectionTimeout 예외 다발
  • MySQL SHOW PROCESSLIST에서 sleep 상태의 커넥션이 비정상적으로 많음
  • 시간이 지날수록 커넥션 수가 줄지 않음
반응형

🔍 커넥션 누수가 발생하는 코드 패턴

1. try-finally 없이 close 누락

Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement("SELECT * FROM user");
ResultSet rs = ps.executeQuery();
// close() 호출 생략됨!

✅ 해결: 반드시 finally에서 닫아주기

try {
  conn = dataSource.getConnection();
  // 작업 수행
} finally {
  if (rs != null) rs.close();
  if (ps != null) ps.close();
  if (conn != null) conn.close();
}

2. 예외 발생 후 close() 호출되지 않음

try {
  conn = dataSource.getConnection();
  int x = 10 / 0;  // 예외 발생
} catch (Exception e) {
  log.error("예외", e);
}
conn.close();  // 이 줄 실행되지 않음

✅ 해결: try-catch-finally 구조를 반드시 활용

3. 커넥션을 서비스 계층까지 넘겨서 사용

public void logic() {
  Connection conn = dataSource.getConnection();
  userService.doSomething(conn);  // close 책임 불명확
}

✅ 해결: 커넥션은 획득한 위치에서 직접 close해야 함

반응형

🛠️ 커넥션 누수 진단법

1. HikariCP leakDetectionThreshold 설정

spring:
  datasource:
    hikari:
      leak-detection-threshold: 2000  # 2초 넘으면 누수 의심 로그
  • 설정된 시간 안에 커넥션이 반납되지 않으면 경고 로그 출력
  • 실무에서 가장 빠르고 효과적인 진단 도구

2. JMX, VisualVM, Actuator 활용

  • JMX를 통해 현재 커넥션 수 확인 가능
  • /actuator/metrics/hikaricp.connections.active 등도 활용 가능

3. MySQL SHOW PROCESSLIST

SHOW PROCESSLIST;
  • Command가 Sleep이고 Time이 비정상적으로 긴 커넥션 → 누수 가능성 있음
  • 사용자의 IP, 실행 쿼리 힌트 등을 통해 추적 가능

🔐 커넥션 누수 예방 전략

  • try-with-resources 사용 (Java 7 이상)
try (Connection conn = dataSource.getConnection();
     PreparedStatement ps = conn.prepareStatement("...")) {
  // 자동 close
}
  • Service 계층에서는 직접 커넥션 획득하지 않기
  • 커넥션 획득은 Repository 계층 내부에 국한
  • @Transactional을 활용해 트랜잭션+커넥션을 Spring이 관리하게 하자

📌 실무 팁: HikariCP 설정 조합

spring:
  datasource:
    hikari:
      maximum-pool-size: 20
      max-lifetime: 1800000
      idle-timeout: 600000
      connection-timeout: 30000
      leak-detection-threshold: 5000
  • leak-detection-threshold를 적절히 설정하면 디버깅이 쉬움
  • 너무 낮게 설정하면 정상 커넥션도 의심 로그가 출력되므로 주의

✅ 정리 요약

  • 커넥션 누수는 반드시 사전에 방지하고 즉시 탐지 가능한 구조가 되어야 한다
  • try-with-resources와 @Transactional 활용이 핵심
  • Spring Boot + HikariCP에서는 leak detection 설정을 적극 사용
  • 누수 발생 시 MySQL과 로그를 동시에 추적해야 정확한 원인 분석이 가능

📘 공식 문서 참고

 

반응형