← 목록으로Troubleshooting

DB 서버 메모리 부족 + Swap 사용 — MariaDB 세션 누적 원인 분석

DB 서버 메모리가 지속적으로 차오르고 Swap까지 사용하는 현상의 원인을 MariaDB 세션 수와 HikariCP 커넥션 풀 설정에서 찾아 분석한 트러블슈팅 기록

TroubleshootingMemoryJavaDevOps
2025-08-08

문제 인식

운영 중인 서비스의 DB 서버에서 메모리 사용량이 지속적으로 증가하고, Swap 메모리까지 사용하는 현상이 확인되었습니다.

Grafana 대시보드에서 메모리 사용량이 우상향하는 패턴이 관찰되었고, Swap 사용량도 함께 증가하고 있었습니다.

메모리 및 Swap 사용량 추이


프로세스 분석

ps aux --sort=-%mem 명령어로 메모리 점유 프로세스를 확인한 결과, MariaDB 프로세스(mariadb -u root -p)가 20개 이상 실행 중이었습니다.

각 프로세스가 약 2.3~2.5%의 메모리를 점유하고 있었으며, 이들의 합산이 전체 메모리의 상당 부분을 차지하고 있었습니다.


DB 세션 확인

운영 DB

MariaDB [(none)]> SHOW PROCESSLIST;

운영 DB 세션 목록

운영 DB의 세션 수는 약 10개로, 모두 Sleep 상태였지만 정상 범위 내였습니다.

개발 DB

MariaDB [(none)]> SHOW FULL PROCESSLIST;

개발 DB 세션 목록 — 40개 이상

개발 DB의 세션 수는 40개 이상으로, 운영 대비 4배나 많았습니다. 대부분 Sleep 상태로 유휴 커넥션이 반환되지 않고 누적되어 있었습니다.


원인 분석 — HikariCP 커넥션 풀 설정

애플리케이션의 DB 커넥션 풀 설정(HikariCP)을 확인했습니다.

HikariCP 설정

hikari:
  pool-name: jpa-hikari-pool
  maximum-pool-size: 30
  minimum-idle: 10
  idle-timeout: 30000
  max-lifetime: 1800000
  connection-timeout: 30000
  auto-commit: false
설정의미
maximum-pool-size30최대 커넥션 수
minimum-idle10최소 유휴 커넥션 수
idle-timeout30,000ms (30초)유휴 커넥션 제거 대기 시간
max-lifetime1,800,000ms (30분)커넥션 최대 수명

운영 vs 개발 세션 수 차이 원인

  • 운영: 트래픽이 일정하고, max-lifetime(30분) 경과 후 커넥션이 갱신되면서 minimum-idle(10개) 수준으로 유지
  • 개발: 여러 개발자가 동시에 접속하거나 테스트를 반복하면서 커넥션이 maximum-pool-size(30개) 근처까지 생성되고, 유휴 상태로 누적

max-lifetime: 1800000(30분)이 지나면 커넥션이 갱신되면서 10개 수준으로 줄어드는 패턴이 확인되었습니다.


근본적 문제 — 개발/운영 DB 동일 서버

포트를 분리하여 운영 DB와 개발 DB를 같은 서버에서 운영하고 있었지만, 개발 DB의 세션 누적이 운영 DB 서버의 메모리에 직접적인 영향을 주고 있었습니다.

이는 운영 안정성 관점에서 리스크가 큰 구조입니다.


대응 방향

  1. 개발 DB 분리: 개발 DB를 별도 테스트 서버로 이전하여 운영 서버 메모리 영향 제거
  2. 커넥션 풀 최적화: 개발 환경의 maximum-pool-size를 줄이고, idle-timeout을 더 짧게 설정
  3. 모니터링 강화: DB 세션 수 추이를 지속적으로 모니터링하여 비정상 누적 조기 감지
  4. Swap 사용량 알람: Swap 사용이 일정 수준을 넘으면 알람 발생하도록 설정

마무리

"메모리가 왜 차지?"에서 시작해 ps auxSHOW PROCESSLIST → HikariCP 설정 확인 순서로 원인을 추적했습니다.

DB 서버의 메모리 문제는 단순히 쿼리 성능만의 문제가 아니라, 커넥션 풀 설정과 환경 분리 같은 인프라 구조적 요소에서 비롯될 수 있다는 점을 확인한 케이스였습니다.