一键导入
hikaricp-tuning-oracle-mysql
HikariCP 커넥션 풀 튜닝 가이드 - Oracle/MySQL 환경 필수 파라미터, DB별 datasource properties, Leak 탐지, Pool Exhaustion 진단, 모니터링
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
HikariCP 커넥션 풀 튜닝 가이드 - Oracle/MySQL 환경 필수 파라미터, DB별 datasource properties, Leak 탐지, Pool Exhaustion 진단, 모니터링
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | hikaricp-tuning-oracle-mysql |
| description | HikariCP 커넥션 풀 튜닝 가이드 - Oracle/MySQL 환경 필수 파라미터, DB별 datasource properties, Leak 탐지, Pool Exhaustion 진단, 모니터링 |
소스: https://github.com/brettwooldridge/HikariCP | https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration | https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing | https://github.com/brettwooldridge/HikariCP/wiki/Rapid-Recovery 검증일: 2026-04-22
주의: 이 문서는 HikariCP 3.4.5(레거시) ~ 5.x(현재 Spring Boot 3.x 번들) 기준입니다. 이 범위에서 API 및 설정 키는 사실상 동일하므로 통합 가이드로 사용 가능합니다. 7.x에서 일부 Breaking Change가 있으므로 최신 버전 사용 시 공식 changelog를 확인하세요.
| 파라미터 | 기본값 | 최소값 | 설명 |
|---|---|---|---|
maximumPoolSize | 10 | — | 풀이 가질 수 있는 최대 커넥션 수(유휴 + 사용 중) |
minimumIdle | maximumPoolSize와 동일 | — | 유지할 최소 유휴 커넥션 수 (공식 권장: 건드리지 말 것) |
connectionTimeout | 30000ms (30초) | 250ms | 클라이언트가 커넥션을 기다릴 최대 시간 |
idleTimeout | 600000ms (10분) | 10000ms | 유휴 커넥션이 제거되기 전 대기 시간. minimumIdle < maximumPoolSize일 때만 적용 |
maxLifetime | 1800000ms (30분) | 30000ms | 커넥션의 최대 수명. 반드시 DB wait_timeout보다 짧게 |
keepaliveTime | 120000ms (2분) | 30000ms | 유휴 커넥션 ping 주기. maxLifetime보다 작아야 함 |
validationTimeout | 5000ms | 250ms | 커넥션 유효성 검증 최대 시간 |
leakDetectionThreshold | 0 (비활성) | 2000ms | 커넥션 누수 의심 경고 임계값. 0이면 비활성화 |
PostgreSQL 프로젝트 기반 공식:
connections = ((core_count * 2) + effective_spindle_count)
예시: 4-core i7 + HDD 1개 → (4 × 2) + 1 = 9
주의: HikariCP 공식 문서는 **"작은 풀이 더 빠르다"**는 원칙을 명시합니다. Oracle 실증 사례에서 커넥션을 2048 → 96으로 줄이자 응답 시간이 ~100ms → ~2ms로 50배 개선되었습니다. 커넥션을 무작정 늘리는 것은 성능을 오히려 해칩니다.
pool_size = (max_threads × (max_connections_per_thread - 1)) + 1
예시: 한 트랜잭션에서 커넥션 4개를 동시에 보유하는 스레드가 3개라면 → 3 × (4 - 1) + 1 = 10
공식 문서는 minimumIdle을 **기본값 그대로 두는 것(=maximumPoolSize와 동일)**을 권장합니다. 이유는 응답시간 변동을 줄이는 고정 크기 풀(fixed-size pool) 동작이 일반적으로 더 우수하기 때문입니다.
wait_timeout(MySQL)이나 유사 제한보다 최소 30초 이상 짧게 설정maxLifetime ≤ (DB wait_timeout - 30s)환경별 구체 권장값:
| DB wait_timeout | 권장 maxLifetime | 설정값 (ms) |
|---|---|---|
| 28800s (MySQL 기본 8시간) | HikariCP 기본값 유지 권장 | 1800000 (30분) |
| 3600s (축소 운영 1시간) | ≤ 3570s | 3500000 (58분) |
| 1800s (축소 운영 30분) | ≤ 1770s | 1700000 (약 28분) |
| 600s (축소 운영 10분) | ≤ 570s | 560000 (약 9분) |
wait_timeout이 축소되어 있는 경우가 흔하므로 설정 전 DBA·운영팀에 반드시 확인jdbcUrl=jdbc:mysql://host:3306/dbname
username=...
password=...
dataSource.cachePrepStmts=true
dataSource.prepStmtCacheSize=250
dataSource.prepStmtCacheSqlLimit=2048
dataSource.useServerPrepStmts=true
dataSource.useLocalSessionState=true
dataSource.rewriteBatchedStatements=true
dataSource.cacheResultSetMetadata=true
dataSource.cacheServerConfiguration=true
dataSource.elideSetAutoCommits=true
dataSource.maintainTimeStats=false
속성별 효과:
| 속성 | 효과 |
|---|---|
cachePrepStmts=true | PreparedStatement 캐시 활성화 (MySQL 드라이버 기본값 false). 이것이 true여야 prepStmtCacheSize/prepStmtCacheSqlLimit이 의미 있음 |
prepStmtCacheSize=250 | 커넥션당 캐시할 PreparedStatement 수 (드라이버 기본 25). 공식 권장: 250~500 |
prepStmtCacheSqlLimit=2048 | 캐시 대상 SQL 최대 길이 (드라이버 기본 256 바이트). ORM 생성 SQL 대응 |
useServerPrepStmts=true | 서버 사이드 PreparedStatement 사용 (성능 향상) |
useLocalSessionState=true | autoCommit/isolation 상태를 로컬 캐시해 불필요한 서버 왕복 제거 |
rewriteBatchedStatements=true | 배치 INSERT/UPDATE를 단일 문으로 재작성하여 대량 처리 성능 향상 |
MySQL Rapid Recovery (네트워크 장애 복구):
dataSource.socketTimeout=30000 # 가장 긴 트랜잭션의 2~3배, 또는 30초 이상
Oracle JDBC 드라이버 고유 속성을 dataSourceProperties로 전달합니다.
jdbcUrl=jdbc:oracle:thin:@host:1521/SERVICE
# 타임아웃 (드라이버 단 소켓 타임아웃)
dataSource.oracle.net.CONNECT_TIMEOUT=10000 # ms, 최초 TCP 연결 타임아웃
dataSource.oracle.jdbc.ReadTimeout=30000 # ms, 소켓 read 타임아웃
# 커넥션 검증 — 기본 NETWORK는 비용이 큼
dataSource.oracle.jdbc.defaultConnectionValidation=LOCAL
주의: Oracle JDBC의
oracle.jdbc.defaultConnectionValidation기본값은NETWORK이며, 이는 borrow 시마다 서버 왕복이 발생해 비용이 큽니다. 대부분의 애플리케이션에서는LOCAL또는SOCKET으로 변경하는 것이 권장됩니다.
defaultAutoCommit 관련 주의:
autoCommit 기본값은 true@Transactional을 사용하면 Spring이 트랜잭션 경계에서 autoCommit을 조정하므로 HikariCP 레벨 값은 영향이 제한적autoCommit=false로 두는 것이 흔한 관행주의:
defaultAutoCommit이라는 키는 Apache DBCP의 설정명입니다. HikariCP에서 동일 역할의 키는autoCommit(카멜케이스)입니다.
Oracle Rapid Recovery:
oracle.net.CONNECT_TIMEOUT: 연결 요청이 블로킹되지 않도록 10초 전후 설정oracle.jdbc.ReadTimeout: 쿼리 결과 수신 타임아웃. 가장 긴 쿼리의 2~3배spring:
datasource:
url: jdbc:mysql://localhost:3306/appdb?useSSL=false&serverTimezone=Asia/Seoul
username: ${DB_USER}
password: ${DB_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
pool-name: MySQLMainPool
maximum-pool-size: 20
minimum-idle: 20 # maximumPoolSize와 동일 권장
connection-timeout: 30000 # 30초
idle-timeout: 600000 # 10분
max-lifetime: 1700000 # DB wait_timeout(1800초)보다 짧게
keepalive-time: 120000 # 2분
validation-timeout: 5000
leak-detection-threshold: 60000 # 60초 이상 반환 안 되면 누수 의심
data-source-properties:
cachePrepStmts: true
prepStmtCacheSize: 250
prepStmtCacheSqlLimit: 2048
useServerPrepStmts: true
useLocalSessionState: true
rewriteBatchedStatements: true
cacheResultSetMetadata: true
cacheServerConfiguration: true
elideSetAutoCommits: true
maintainTimeStats: false
socketTimeout: 30000
spring:
datasource:
url: jdbc:oracle:thin:@//oracle-host:1521/ORCL
username: ${DB_USER}
password: ${DB_PASSWORD}
driver-class-name: oracle.jdbc.OracleDriver
hikari:
pool-name: OracleMainPool
maximum-pool-size: 20
minimum-idle: 20
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1700000
keepalive-time: 120000
leak-detection-threshold: 60000
auto-commit: false # 명시적 트랜잭션 관리 시
data-source-properties:
oracle.net.CONNECT_TIMEOUT: 10000
oracle.jdbc.ReadTimeout: 30000
oracle.jdbc.defaultConnectionValidation: LOCAL
oracle.jdbc.implicitStatementCacheSize: 100
spring:
datasource:
hikari:
leak-detection-threshold: 60000 # 60초. 최소값 2000ms
WARN com.zaxxer.hikari.pool.ProxyLeakTask : Connection leak detection triggered for
oracle.jdbc.driver.T4CConnection@abc123 on thread http-nio-8080-exec-3,
stack trace follows
java.lang.Exception: Apparent connection leak detected
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:128)
at com.example.service.UserService.findAll(UserService.java:42)
...
try-with-resources/@Transactional 없이 커넥션 획득 후 close() 누락leakDetectionThreshold를 짧게(10~30초) 설정해 즉각 감지HikariPool-1 - Connection is not available, request timed out after 30000ms.
Total connections: 20, active: 20, idle: 0, waiting: 5
의미: maximumPoolSize(20)개가 모두 사용 중, 5개 스레드가 connectionTimeout 동안 대기하다 실패.
커넥션 누수인가?
leakDetectionThreshold를 활성화하고 로그 확인느린 쿼리가 커넥션을 오래 잡고 있는가?
SHOW PROCESSLIST (MySQL), V$SESSION (Oracle)로 오래 실행 중인 세션 확인풀 크기가 부족한가? (누수·느린 쿼리가 아닐 경우)
(core × 2) + spindle멀티 DataSource의 총 커넥션이 DB max_connections를 넘지는 않는가?
SHOW VARIABLES LIKE 'max_connections'SELECT value FROM v$parameter WHERE name='processes';트랜잭션이 비정상적으로 길어지는가?
@Transactional 메서드 내부에서 외부 HTTP 호출 등 오래 걸리는 I/O 수행 금지| 접근 | 효과 | 주의 |
|---|---|---|
maximumPoolSize 증가 | 단기 완화 | 근본 원인이 누수/느린 쿼리면 DB 과부하로 번질 수 있음 |
connectionTimeout 증가 | 실패 대신 느린 응답으로 전환 | UX 악화, 카스케이딩 장애 위험 |
| 누수 코드 수정 | 근본 해결 | 최우선 |
| 느린 쿼리 최적화 | 근본 해결 | DB 부하도 함께 감소 |
HikariCP는 Micrometer에 Meter를 자동 등록합니다. Spring Boot Actuator + Micrometer가 클래스패스에 있으면 별도 설정 없이 /actuator/metrics에 노출됩니다.
| 메트릭 | 의미 | 경보 기준 예시 |
|---|---|---|
hikaricp.connections | 풀 내 총 커넥션 수 | — |
hikaricp.connections.active | 현재 사용 중인 커넥션 수 | maximumPoolSize에 근접하면 위험 |
hikaricp.connections.idle | 유휴 커넥션 수 | — |
hikaricp.connections.pending | 커넥션을 기다리는 스레드 수 | > 0이 지속되면 풀 부족 신호 |
hikaricp.connections.timeout | connectionTimeout으로 실패한 횟수 (Counter) | 증가하면 즉시 조사 |
hikaricp.connections.usage | 커넥션 대여 → 반환까지 소요 시간 (Timer) | p99가 급증하면 트랜잭션 길어짐 |
hikaricp.connections.acquire | 커넥션 획득 소요 시간 (Timer) | p99 급증은 풀 부족 신호 |
hikaricp.connections.creation | 새 커넥션 생성 소요 시간 (Timer) | DB 네트워크 지연 지표 |
management:
endpoints:
web:
exposure:
include: health, metrics, prometheus
metrics:
tags:
application: ${spring.application.name}
pool-name을 명시적으로 설정하면 여러 풀 구분이 쉬워집니다 (pool: MySQLMainPool 태그로 노출).
app:
datasource:
oracle:
url: jdbc:oracle:thin:@//oracle-host:1521/ORCL
username: ${ORACLE_USER}
password: ${ORACLE_PASSWORD}
driver-class-name: oracle.jdbc.OracleDriver
hikari:
pool-name: OraclePool
maximum-pool-size: 15
minimum-idle: 15
max-lifetime: 1700000
leak-detection-threshold: 60000
data-source-properties:
oracle.net.CONNECT_TIMEOUT: 10000
oracle.jdbc.ReadTimeout: 30000
oracle.jdbc.defaultConnectionValidation: LOCAL
mysql:
url: jdbc:mysql://mysql-host:3306/appdb
username: ${MYSQL_USER}
password: ${MYSQL_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
pool-name: MySQLPool
maximum-pool-size: 20
minimum-idle: 20
max-lifetime: 1700000
leak-detection-threshold: 60000
data-source-properties:
cachePrepStmts: true
prepStmtCacheSize: 250
prepStmtCacheSqlLimit: 2048
useServerPrepStmts: true
useLocalSessionState: true
rewriteBatchedStatements: true
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties("app.datasource.oracle")
public DataSourceProperties oracleProps() {
return new DataSourceProperties();
}
@Bean
@ConfigurationProperties("app.datasource.oracle.hikari")
public HikariDataSource oracleDataSource(
@Qualifier("oracleProps") DataSourceProperties props) {
return props.initializeDataSourceBuilder()
.type(HikariDataSource.class)
.build();
}
// mysql도 동일 패턴 + @Primary는 상황에 맞게 한쪽에만
}
각 앱 인스턴스가 갖는 커넥션 총합을 반드시 추산합니다.
총 커넥션 = Σ(풀별 maximumPoolSize) × 앱 인스턴스 수
예시:
max_connections를 초과하지 않는지 반드시 확인(core_count × 2) + effective_spindle_counthikaricp.connections.pending이 0에 수렴하고 active가 maximumPoolSize에 항상 닿지 않으면 여유 있음주의: 커넥션을 늘려 TPS가 개선되는 것처럼 보여도, DB 서버의 컨텍스트 스위칭·락 경합이 증가해 p99 지연이 악화되는 경우가 흔합니다. 처리량만 보지 말고 p95/p99를 반드시 함께 확인하세요.
HikariCP 3.4.5의 확인된 특성:
3.4.5 → 최신(5.x) 차이 요약:
| 항목 | 3.4.5 | 5.x (Spring Boot 3.x 번들) |
|---|---|---|
| 최소 Java | 8 | 11 |
| API / 설정 키 | 동일 | 동일 |
| Micrometer 메트릭 이름 | 동일 | 동일 |
| 성능 | 유사, 대부분 내부 최적화 | 소폭 개선 |
주의: 3.4.5에서
keepaliveTime은 존재하지 않습니다.keepaliveTime은 4.0.x부터 추가되었습니다. 3.4.5 환경에서는maxLifetime+ 드라이버 단socketTimeout/oracle.jdbc.ReadTimeout으로 대체하여 네트워크 장애 복구를 설계해야 합니다.
| Spring Boot | 번들 HikariCP | 최소 Java |
|---|---|---|
| 2.0.x | 2.7.x | 8 |
| 2.4.x | 3.4.x | 8 |
| 2.7.x | 4.0.3 → 5.0.1 (2.7 중반부터 5.x) | 8 |
| 3.0.x ~ 3.2.x | 5.0.x | 17 |
| 3.3.x ~ 3.4.x | 5.1.x | 17 |
주의: 정확한 번들 버전은
mvn dependency:tree | grep HikariCP또는./gradlew dependencies | grep HikariCP로 현재 프로젝트에서 직접 확인하세요. 위 표는 개괄이며 패치 버전은 유동적입니다.
번들 버전이 아닌 특정 버전을 사용하려면:
<!-- Maven -->
<properties>
<hikaricp.version>5.1.0</hikaricp.version>
</properties>
// Gradle
ext['hikaricp.version'] = '5.1.0'
maxLifetime < DB wait_timeout 최소 30초 차이 확인leakDetectionThreshold 활성화 (최소 2000ms)maximumPoolSize가 공식 기반인가? 근거 없는 큰 값 아닌가?minimumIdle을 maximumPoolSize와 동일하게 유지(또는 근거 있는 값으로)cachePrepStmts 외 6종 속성 설정CONNECT_TIMEOUT / ReadTimeout / defaultConnectionValidation=LOCALpool-name 명시로 메트릭/로그에서 풀 구분/metrics에 hikaricp.connections.* 노출 확인max_connections의 80% 이하인가기준: Spring Boot 4.0 번들 HikariCP 7.0.x / Java 17+ 소스: https://github.com/brettwooldridge/HikariCP/blob/dev/CHANGES https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-4.0-Release-Notes 검증일: 2026-06-19
| Spring Boot | 번들 HikariCP |
|---|---|
| 2.7.x | 4.0.3 ~ 5.0.1 |
| 3.0.x ~ 3.2.x | 5.0.x |
| 3.3.x ~ 3.5.x | 5.1.x |
| 4.0.x ~ 4.1.x | 7.0.x |
설정 파라미터 이름 자체는 변경 없다. 기존 application.yml의 spring.datasource.hikari.* 키 이름을 그대로 사용 가능.
| 항목 | 내용 |
|---|---|
| 설정 키 변경 | 없음 — 기존 yml 그대로 동작 |
HikariCredentialsProvider | 신규 추가 — 동적 자격증명 공급자 인터페이스 |
| 가상 스레드 최적화 | ConcurrentBag의 virtual-thread yield 스핀 최소화 |
| 메트릭 이름 | 변경 없음 (hikaricp.connections.*) |
AWS Secrets Manager, Vault 동적 시크릿 등 자격증명을 동적으로 제공해야 하는 환경을 위한 확장 포인트.
import com.zaxxer.hikari.HikariCredentialsProvider;
public class AwsIamCredentialsProvider implements HikariCredentialsProvider {
@Override
public String getUsername() { return fetchUsernameFromSecretsManager(); }
@Override
public String getPassword() { return generateIamAuthToken(); }
}
// HikariConfig에 등록
config.setCredentialsProvider(new AwsIamCredentialsProvider());
Spring Boot 4.x에서 가상 스레드 활성화 시 HikariCP 7.x의 ConcurrentBag 최적화가 자동 적용된다. 별도 설정 변경 불필요.
주의: Virtual Thread 환경에서는 물리 스레드 기반 공식인
(core_count * 2) + spindle보다 낮은 커넥션 수에서도 높은 처리량이 유지되는 경우가 많다. 기존 값부터 시작해 실측값을 기반으로 조정할 것.
Spring Security 5.5.x + jjwt 0.10.7 레거시 JWT 인증 - WebSecurityConfigurerAdapter, OncePerRequestFilter, javax.servlet 환경
Spring Boot 3.x + Spring Security 6.x + jjwt 0.12.x 기반 모던 JWT 인증 패턴. SecurityFilterChain Bean, 람다 DSL, jakarta.servlet, Virtual Threads 적용
Unity 6 LTS 2D 모바일 게임용 uGUI 시스템 전문 스킬. Canvas/RectTransform/TextMeshPro, 모바일 UI 패턴(팝업·무한 스크롤·광고·IAP), 성능 최적화, UI Toolkit과의 선택 기준 포함.
아크라시아(akrasia, 자제력 없음) 학술 논쟁의 핵심 구도와 주요 연구자·문헌을 빠르게 파악할 수 있는 도메인 지식 스킬. 도덕윤리교육 전공 대학원생(석/박사)이 학위논문·KCI 투고·세미나 준비 시 고대–현대–한국 학계–도덕심리학 흐름을 한 번에 짚도록 구성. <example>사용자: "아리스토텔레스의 propeteia와 astheneia 구분을 인용하려는데 출처를 알려줘"</example> <example>사용자: "데이비슨이 의지박약을 어떻게 가능하다고 봤는지 핵심 논증을 정리해줘"</example> <example>사용자: "한국 도덕교육 학계에서 아크라시아 다룬 논문 있어?"</example>
아리스토텔레스 『니코마코스 윤리학』에서 akrasia(자제력없음)와 akolasia(무절제)의 5축 차이를 정밀하게 정리한 학위논문 자료 스킬. NE VII.4 1147b20-1148b14, VII.8 1150b29-1151a28, III.10-12 1117b23-1119b18 절별 분해와 표준 학자 해석(Bostock, Broadie-Rowe, Pakaluk, Hursthouse, Charles 등)을 포함. 도덕교육 적용을 위한 두 상태 차이의 함의 및 한국어 번역어 처리 권장안 제공. <example>사용자: "akrates와 akolastos를 prohairesis 측면에서 어떻게 구분해야 하나요?"</example> <example>사용자: "NE VII.4의 ἁπλῶς akrasia가 akolasia와 어떻게 갈라지는지 절별 분해해주세요"</example> <example>사용자: "Hursthouse의 연속체 모델을 도덕교육 적용 절에서 어떻게 활용할 수 있나요?"</example>
한국 위기 대응 자원(자살·자해·정신건강·여성·청소년·노인·다문화) 핫라인과 앱·챗봇 안전 가드 응답 패턴 종합. 꿈 해몽·정신건강 앱 등 자가 진단/감정 콘텐츠 도메인에서 위험 신호 포착 시 안전한 자원 안내 문구를 작성할 때 참조. <example>사용자: "꿈 해몽 앱에 위기 안내 문구를 어떻게 넣을까?"</example> <example>사용자: "한국에서 자살예방 핫라인 번호가 어떻게 바뀌었지?"</example> <example>사용자: "정신건강 챗봇 안전 가드 응답 템플릿을 짜줘"</example>