반응형
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과 로그를 동시에 추적해야 정확한 원인 분석이 가능
📘 공식 문서 참고
- https://github.com/brettwooldridge/HikariCP#leak-detection
- https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html
반응형
'DB' 카테고리의 다른 글
| [MySQL] 문자열 추출 함수: LEFT, RIGHT, SUBSTRING 정리 (0) | 2025.07.19 |
|---|---|
| [MySQL] 문자열 연결 함수: CONCAT, CONCAT_WS 활용법 (0) | 2025.07.19 |
| [MySQL] 문자열 길이 함수: LENGTH vs CHAR_LENGTH 정리 (3) | 2025.07.19 |
| [MySQL] (연결최적화6️⃣) 실무 연결 설정 체크리스트 총정리 (1) | 2025.07.19 |
| [MySQL] (연결최적화4️⃣) 트랜잭션 전파 방식과 커넥션 이슈 분석 (0) | 2025.07.18 |
| [MySQL] (연결최적화3️⃣) 커넥션 타임아웃 설정과 오류 해결법 (0) | 2025.07.18 |
| [MySQL] (연결최적화2️⃣) 커넥션 풀의 개념과 실무 설정 가이드 (0) | 2025.07.18 |
| [MySQL] (연결최적화1️⃣) JDBC 드라이버 설정 핵심 옵션 정리 (0) | 2025.07.18 |