1. 문서 제목
- DB 커넥션 풀 사이징과 데드락 — API가 느려질 때 원인을 좁히는 순서
2. 기술 개요 요약
DB 성능 저하는 보통 "쿼리 문제 / 락 경합 / 커넥션 풀 고갈 / 리소스 부족" 네 갈래 중 하나에서 시작된다. 이 문서는 그중 커넥션 풀 사이징의 기준(코어 수 vs 쓰레드 수)과 락 경합의 대표 사례인 데드락의 발생 원리, 그리고 API 지연이 발생했을 때 실무에서 원인을 좁혀가는 순서를 정리한다. SHOW PROCESSLIST와 세부 모니터링 지표는 이미 다뤘으므로 여기서는 커넥션 풀 사이징 원리와 데드락에 집중한다.
3. 핵심 기능/개념 정리
| 개념 | 설명 | 실무 포인트 |
|---|---|---|
| 커넥션 풀 사이징 공식의 "쓰레드" | HikariCP 등에서 인용되는 (core_count * 2) + effective_spindle_count의 core_count는 DB 서버의 CPU 코어 수 |
WAS 요청 처리 쓰레드 수와는 별개 개념. DB 커넥션은 WAS 쓰레드 수보다 훨씬 작게(코어 수 기반) 유지하는 것이 일반적 |
| WAS 쓰레드 풀 vs DB 커넥션 풀 | WAS 쓰레드는 I/O 대기가 많아 수백 개 단위로 넉넉히, DB 커넥션은 코어 수 기반으로 수십 개 수준으로 제한 | 초과 요청은 커넥션 풀 안에서 대기(큐잉)하고, 길어지면 connection timeout으로 이어짐 |
| 데드락 | 두 개 이상의 트랜잭션이 서로가 가진 락을 기다리며 순환 대기에 빠지는 상태 | 핵심 원인은 "락 획득 순서 불일치". 공유 락/배타 락 종류가 핵심이 아니라 순서 불일치가 핵심 |
| InnoDB의 데드락 감지 | wait-for graph로 순환 대기를 즉시 감지(innodb_deadlock_detect=ON이 기본)하고, 수정/삽입/삭제한 행 수가 적어 롤백 비용이 낮은 트랜잭션을 victim으로 롤백 |
애플리케이션은 데드락 예외 발생 시 재시도 로직을 갖춰야 함 |
| 데드락 예방 vs 락 대기 안전장치 | 예방: 락 획득 순서 통일, 트랜잭션 범위 축소, 예외 시 재시도. innodb_lock_wait_timeout(기본 50초)은 엄밀히는 "데드락 예방" 수단이 아니라, wait-for graph가 못 잡는 장시간 락 대기(예: 감지가 꺼진 고동시성 환경, 타 엔진과의 메타데이터 락 대기)에 대한 안전장치 |
타임아웃 발생 시 기본 설정(innodb_rollback_on_timeout=OFF)에서는 트랜잭션 전체가 아니라 해당 statement만 롤백됨 — 트랜잭션은 계속 열려 있으므로 애플리케이션이 명시적으로 처리해야 함 |
| 장애 대응 5단계 | ① 모니터링(APM, DB CPU/메모리, active/pending connection, slow query, lock wait time) ② SHOW PROCESSLIST/lock wait 정보 확인 ③ 원인 분류(쿼리/락 경합/커넥션 풀/리소스) ④ 원인별 대응 ⑤ 재발 방지 |
커넥션 수 증가는 원인이 아니라 증상인 경우가 많다 — 무작정 풀 크기부터 늘리지 말 것 |
4. 사용 예시 및 코드 스니펫
데드락 발생 시나리오:
Transaction A: row 1 락 획득 -> row 2 락 대기
Transaction B: row 2 락 획득 -> row 1 락 대기
=> 서로 상대가 끝나기만 기다리는 순환 대기 (데드락)
데드락 예방 — 락 획득 순서를 통일:
-- 잘못된 예: 트랜잭션마다 락 획득 순서가 다름
-- TX A: UPDATE t WHERE id=1; UPDATE t WHERE id=2;
-- TX B: UPDATE t WHERE id=2; UPDATE t WHERE id=1;
-- 올바른 예: 항상 id 오름차순으로 락 획득
-- TX A, TX B 모두: UPDATE t WHERE id=1; UPDATE t WHERE id=2;
장애 대응 진단 흐름:
1. APM/DB 모니터링으로 현상 확인
(API latency, DB CPU/메모리, active/pending connection, slow query 수, lock wait time)
2. SHOW PROCESSLIST / InnoDB lock wait 정보 확인
(오래 실행 중인 쿼리, 락 대기 세션, 장시간 열린 트랜잭션)
3. 원인 분류
- 쿼리 문제 (풀스캔, 인덱스 미사용) -> EXPLAIN으로 튜닝
- 락 경합 (장시간 트랜잭션) -> 트랜잭션 범위 축소, 락 순서 통일
- 커넥션 풀 고갈 -> 풀 크기/timeout 점검 (단, 먼저 반환 지연 원인부터 확인)
- 리소스 부족 -> 스케일링 검토
4. 재발 방지: 외부 API 호출을 트랜잭션 밖으로 분리, lock wait time/slow query/active connection 알림 설정
5. 실제 사용 시 주의점 / Best Practice
- 커넥션 풀 크기를 WAS 쓰레드 수에 맞춰 키우는 것은 잘못된 접근이다. DB가 감당 가능한 동시 쿼리 수(코어 수 기반)를 넘는 커넥션은 컨텍스트 스위칭·락 경합·캐시 경쟁만 늘려 오히려 처리량을 떨어뜨릴 수 있다.
- "커넥션이 부족하다"는 신호를 보면 먼저 어떤 쿼리·트랜잭션이 커넥션을 오래 점유하는지부터 확인해야 한다. 슬로우 쿼리나 락 대기로 반환이 늦어지는 게 근본 원인인데 풀 크기만 늘리면 증상만 미루는 셈이다.
- 데드락은 "발생 자체를 막는 것"보다 "락 획득 순서를 프로젝트 전체에서 통일하는 규칙"으로 예방 확률을 크게 낮출 수 있다. 코드 리뷰 시 여러 테이블/row를 갱신하는 트랜잭션의 락 순서를 점검하는 것이 실질적으로 도움이 된다.
- 외부 API 호출(결제, 알림 등)을 DB 트랜잭션 안에 넣으면 트랜잭션이 길어져 락 점유 시간이 늘고 데드락·커넥션 고갈 위험이 함께 커진다. 트랜잭션 밖으로 분리하는 것이 기본 원칙이다.
6. 참고자료 / 공식 문서 출처
- HikariCP, "About Pool Sizing": https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing
- MySQL Reference Manual, InnoDB Deadlocks(개요): https://dev.mysql.com/doc/refman/8.4/en/innodb-deadlocks.html
- MySQL Reference Manual, Deadlock Detection(wait-for graph·victim 선정 기준 상세): https://dev.mysql.com/doc/refman/8.4/en/innodb-deadlock-detection.html
- MySQL Reference Manual,
innodb_lock_wait_timeout: https://dev.mysql.com/doc/refman/8.4/en/innodb-parameters.html#sysvar_innodb_lock_wait_timeout
반응형
'DB > MySQL' 카테고리의 다른 글
| [MySQL] 인덱스 심화 2 — ORDER BY가 인덱스를 타는 조건, 암시적 형변환, 인덱스 없는 UPDATE의 락 확산 (0) | 2026.07.12 |
|---|---|
| [MySQL] 인덱스 심화 — 10%룰, B+Tree 리밸런싱, 복합 인덱스 컬럼 순서 (0) | 2026.07.12 |
| [MySQL] 인덱스 레인지 스캔, 랜덤 I/O, 검색엔진 도입 기준 정리 (0) | 2026.07.11 |
| [MySQL] Replication과 InnoDB Cluster, Sharding은 무엇이 다를까? (0) | 2026.07.11 |
| [MySQL] SHOW PROCESSLIST와 DB 모니터링 메트릭 정리 (0) | 2026.07.10 |
댓글