갑자기 트래픽이 10배 증가했고, DB 커넥션 풀이 고갈되어 서비스가 느려진다면
Hermaeus Mora · · Devops
어떻게 대응할 것인가? 우리는 cnpg를 사용중이고, pg와 pg바운서를 사용하며, transactional 모드를 사용중이다(트랜잭션이 끝나면 즉시 커넥션 반환한다.
풀 고갈이 **"그냥 요청이 많아서"**인지, **"DB가 느려져서 커넥션을 오래 붙잡아서"**인지 구분하는 지표들입니다.
PgBouncer 쪽
SHOW POOLS: 지금 이 순간의 풀 상태
cl_active: 서버 커넥션을 할당받아 쿼리 중인 클라이언트 수cl_waiting: 서버 커넥션이 없어 줄 서서 대기 중인 클라이언트 수. 0보다 크면 풀이 꽉 찼다는 뜻sv_active: PG에 실제로 일하고 있는 커넥션 수.default_pool_size에 붙어 있으면 포화 상태maxwait: 대기열에서 가장 오래 기다린 클라이언트의 대기 시간(초). 이 값이 곧 사용자가 느끼는 추가 지연
SHOW STATS: 누적 통계와 평균
avg_xact_time: 트랜잭션 하나가 서버 커넥션을 붙잡고 있는 평균 시간(μs)avg_wait_time: 클라이언트가 커넥션을 받기까지 기다린 평균 시간
핵심은 avg_xact_time입니다. 풀 처리량은 대략 pool_size ÷ avg_xact_time입니다.
- 평소와 같다면: DB는 정상이고 순수하게 요청량이 많은 것. 풀 증설이 효과가 있습니다.
- 평소보다 늘었다면: DB가 느려져 커넥션 회전이 막힌 것. 풀을 늘리면 오히려 악화됩니다.
CNPG Pooler는 exporter로 cnpg_pgbouncer_pools_cl_waiting, cnpg_pgbouncer_stats_avg_xact_time 같은 메트릭을 노출하니 Grafana로 평소 값과 비교하면 편합니다.
PG 쪽
CPU와 IO: 노드나 파드의 CPU 사용률, 디스크 IOPS와 latency를 봅니다. CPU가 100%에 가깝거나 IO wait가 높으면 DB 자체가 병목입니다.
pg_stat_activity: 백엔드 하나하나가 지금 뭘 하는지 보여줍니다.
SELECT state, wait_event_type, wait_event, count(*)
FROM pg_stat_activity
WHERE backend_type = 'client backend'
GROUP BY 1,2,3 ORDER BY 4 DESC;wait_event_type = Lock: 행이나 테이블 락 경합. 커넥션을 늘리면 경합이 더 심해집니다.wait_event_type = IO: 디스크 대기. 캐시 미스나 풀스캔을 의심해 볼 수 있습니다.wait_event가 NULL이고state = active: CPU를 쓰며 실제 실행 중인 상태
idle in transaction: 트랜잭션을 열어둔 채 아무것도 안 하는 세션입니다. transaction 모드에서도 이 상태로는 커넥션이 반환되지 않아서 풀을 그냥 점유합니다. 앱이 트랜잭션 안에서 외부 API를 호출하는 경우가 대표적입니다.
SELECT pid, now() - xact_start AS dur, query
FROM pg_stat_activity
WHERE state = 'idle in transaction'
ORDER BY dur DESC;슬로우 쿼리: 지금 오래 걸리고 있는 쿼리는 now() - query_start로 정렬해서 찾습니다. 누적으로 부하를 많이 주는 쿼리는 pg_stat_statements를 total_exec_time 순으로 보면 됩니다. 락을 잡고 있는 범인은 pg_blocking_pids(pid)로 추적합니다.
판단 요약
| 관찰 | 해석 | 대응 |
|---|---|---|
cl_waiting↑, avg_xact_time 그대로, DB CPU 여유 | 순수 트래픽 증가 | 풀 증설 |
avg_xact_time↑, CPU나 IO 포화 | DB 과부하 | 부하 차단, 레플리카 분산, 캐시 |
wait_event Lock 다수 | 락 경합 | 블로커 확인, 필요시 kill |
idle in transaction 다수 | 앱이 커넥션을 붙잡고 있음 | timeout 설정, 앱 수정 |