풀 크기를 정하는 세 가지 숫자
- 부하. 리틀의 법칙에 따라 동시에 쓰이는 커넥션 수는 초당 요청 수 × 커넥션 점유 시간입니다. 초당 200건이 각각 25ms 씩 잡으면 평균 5개가 쓰입니다.
- 교착 방지. 스레드 하나가 커넥션을 둘 잡을 수 있으면(열린 트랜잭션 안의
REQUIRES_NEW등) 풀이Tn × (Cm − 1) + 1보다 작을 때 모든 스레드가 하나씩 쥔 채 두 번째를 기다리며 멈출 수 있습니다. - DB 한도. 모든 인스턴스가 하나의
max_connections를 나눠 씁니다. 관리용·복제·배치 몫을 남기고, 롤링 배포 중 더 뜨는 파드까지 셈해야 합니다.
계산 예시
계산기 기본값 — 인스턴스당 초당 200건, 점유 25ms, 여유 30%, 인스턴스 3대 + 배포 중 1대, DB max_connections 151개 중 10개 예약 — 로 계산하면:
| 항목 | 계산 | 결과 |
|---|---|---|
| 부하 기준 | 200 × 0.025초 × 1.3 | 7 |
| 교착 방지 최소값 | 스레드당 커넥션 1개 | 1 |
| 인스턴스당 DB 한도 | (151 − 10) ÷ (3 + 1) | 35 |
| DB 권장치 (전체) | 코어 8 × 2 + 1 | 17 |
| 권장값 | max(부하, 교착), DB 한도 안에서 | 7 |
인스턴스당 7개는 기본값 10보다 작아 보이지만, 요청이 커넥션을 빨리 돌려주기 때문에 충분합니다. 50개가 필요하다면 고칠 곳은 대개 풀이 아니라 트랜잭션입니다.
풀을 키우기 전에 볼 것
- 트랜잭션 안의 외부 호출.
@Transactional안에서 HTTP 를 호출하면 응답이 올 때까지 커넥션을 잡고 있습니다. 트랜잭션 밖으로 빼면 필요한 풀 크기도 같이 줄어듭니다. - Open Session in View.
spring.jpa.open-in-view는 기본으로 켜져 있어 화면 렌더링까지 커넥션을 잡습니다. 끄기만 해도 점유 시간이 크게 줄어드는 경우가 많습니다. - 느린 쿼리. 4ms 걸릴 쿼리가 400ms 걸리면 같은 트래픽에 커넥션이 100배 필요합니다. DB 를 키우는 것보다 인덱스가 쌉니다.