[MySQL] Too many connections 에러 해결: 실제 장애 사례 및 커넥션 풀 최적화

Hack hack 아바타

웹 서비스의 동시 접속자가 갑자기 늘어나거나 백엔드 소스코드에서 데이터베이스 연결을 제대로 닫지 않으면, 어김없이 “Internal Server Error (500)”와 함께 DB 로그에 “Too many connections”라는 치명적인 에러가 기록됩니다.

이 오류는 MySQL 데이터베이스 서버가 동시에 수용할 수 있는 최대 연결(Connection) 개수를 초과했을 때 발생합니다. 대형 장애로 이어지기 쉬운 이 문제를 해결하기 위해, 에러가 발생하는 구조적인 원인을 진단하고 설정 파일 수정부터 커넥션 풀 최적화까지 실무 중심의 해결책을 정리합니다.

1. 에러 발생 원인과 실제 장애 사례

MySQL은 요청이 올 때마다 하나의 스레드(Thread)를 할당하여 연결을 유지합니다. 서버 메모리(RAM) 고갈을 막기 위해 시스템 내부적으로 max_connections라는 제한 한도를 걸어둡니다.

🚨 실제 장애 사례 (Case Study)
모 이커머스 스타트업은 타임세일 이벤트 오픈 3초 만에 전체 서비스가 마비되었습니다. 원인은 서버 성능 부족이 아니었습니다. 특정 조회 API 코드에서 데이터를 가져온 후 DB 연결을 닫지 않는 ‘커넥션 누수(Connection Leak)’가 발생했고, 수천 명의 사용자가 진입하자마자 좀비 커넥션이 순식간에 최대 제한치를 채워버린 것이 원인이었습니다.

이처럼 백엔드 서버 웹 애플리케이션들과 데이터베이스 사이의 연결 통로가 꽉 막히는 구조는 아래 다이어그램과 같습니다.

  • 원인 1 (트래픽 폭주): 이벤트 등으로 인해 평소보다 수십 배 많은 사용자가 동시에 유입되는 경우.
  • 원인 2 (커넥션 누수): 개발 코드가 DB 조회 후 close()를 누락하여 좀비 세션이 누적되는 경우.
  • 원인 3 (대기 시간 과다): 아무 일도 안 하는 세션이 기본값인 8시간 동안 끊어지지 않고 방치되는 경우.

📌 1세션 핵심 요약: Too many connections는 DB의 최대 연결 한도(max_connections)가 바닥나 발생하는 자원 고갈 장애입니다. 단순 트래픽 폭주보다 코딩 실수로 인한 연결 누수(Leak)가 더 치명적인 주범입니다.

2. 단계별 상황 조치 및 설정 최적화

장애가 발생했을 때 당장 서비스를 살리는 긴급 조치부터, 근본적인 설정을 바꾸는 정석적인 단계를 순서대로 적용해 보세요.

[1단계] 긴급 조치: 좀비 프로세스 강제 종료

우선 급한 불을 끄기 위해 현재 DB 자원을 갉아먹고 있는 유휴 연결들을 찾아 강제로 끊어주어야 합니다.

  • 작업 난이도: 하 (Low) / 소요 시간: 약 2분
# MySQL 관리자 계정으로 접속
mysql -u root -p
# 현재 열려있는 모든 연결 프로세스 목록 조회
SHOW PROCESSLIST;

출력 목록 중 Command 열이 Sleep 상태이면서 Time(대기 시간)이 유독 긴 프로세스의 ID 값을 찾아 강제 종료합니다.

# 예: ID가 123번인 좀비 커넥션 사살
KILL 123;

[2단계] 환경 설정: max_connections 한도 상향

서버 사양(RAM)에 여유가 있다면 MySQL 설정 파일을 직접 수정하여 최대 연결 한도 자체를 높여줍니다.

  • 작업 난이도: 중 (Medium) / 소요 시간: 약 4분
# 리눅스 우분투 기준 MySQL 설정 파일 편집
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
# [mysqld] 섹션 아래의 값을 수정 (없다면 추가)
max_connections = 500

설정을 저장한 뒤, 시스템에 반영하기 위해 데이터베이스 서비스를 재시작합니다.

sudo systemctl restart mysql

[3단계] 효율화 설정: 대기 타임아웃(Timeout) 단축

일을 마치고 대기 상태인 좀비 세션들이 시스템에서 빠르게 떨어져 나가도록 회수 주기를 대폭 줄여줍니다. 기본값 8시간(28800초)을 3분(180초) 내외로 과감히 낮춥니다.

  • 작업 난이도: 중 (Medium) / 소요 시간: 약 2분
# mysqld.cnf 파일 내에 추가 설정
wait_timeout = 180
interactive_timeout = 180

📌 2세션 핵심 요약: 장애 즉시 SHOW PROCESSLISTKILL로 좀비 연결을 처내 숨통을 트이게 하세요. 이후 설정 파일에서 max_connections를 늘리고 wait_timeout을 줄여 자원 회수 속도를 격상시켜야 합니다.

3. 에러 로그 분석과 모니터링 심화

실제 서비스 운영 중 백엔드 애플리케이션 콘솔창에 출력되는 전형적인 에러 로그 스니펫은 다음과 같습니다. 이 로그가 포착된다면 즉시 DB 자원을 점검해야 합니다.

사례: 자바 Spring Boot (HikariCP) 커넥션 풀 고갈 로그 예시

java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30005ms.
Caused by: java.sql.SQLException: Data source rejected establishment of connection, message from server: "Too many connections"

백엔드의 커넥션 풀(HikariCP)이 DB에 연결을 요청했으나, MySQL 서버가 자리가 없다며 요청을 거부해 결국 타임아웃이 터졌음을 증명하는 명확한 지표입니다.

📌 3세션 핵심 요약: 백엔드 로그에 SQLTransientConnectionException 문구가 식별된다면 인프라 단의 네트워크 단절이 아닌, 실제 DB 내부 세션이 100% 가동 중인 자원 임계점 상태를 의미합니다.

4. 자주 묻는 질문 (FAQ)

Q1. max_connections 값은 무조건 크게 잡을수록 좋은가요?
A. 아니요, 위험합니다. 연결 하나당 일정량의 RAM 메모리를 점유하므로, 서버 사양을 고려하지 않고 너무 높이면 트래픽이 몰렸을 때 DB 서버가 메모리 부족(OOM)으로 아예 부팅 불능 상태로 다운될 수 있습니다.

Q2. 백엔드 ‘커넥션 풀(Connection Pool)’과 DB 설정은 어떤 관계인가요?
A. 상호 비례 관계입니다. 백엔드 프로그램이 미리 열어두는 DB 통로 수(Max Pool Size)의 총합이 MySQL의 max_connections보다 작아야 안전합니다. 서버가 여러 대라면 전체 백엔드 풀의 합계를 계산해 DB 용량을 설계해야 합니다.

Q3. Sleep 프로세스가 자꾸만 쌓이는 근본적인 이유는 무엇인가요?
A. 소스코드의 자원 반환 누수 때문입니다. 로직 수행이 끝났음에도 코드가 DB 세션을 명시적으로 끊지 않으면, MySQL은 설정된 타임아웃(wait_timeout) 시간이 끝날 때까지 해당 연결을 무의미하게 유지하게 됩니다.

Q4. 클라우드(AWS RDS) 환경에서도 이 에러가 자주 발생하나요?
A. 네, 특히 사양이 낮을 때 빈번합니다. AWS RDS는 메모리 크기에 비례해 이 제한치가 자동 책정됩니다. 사양이 낮은 인스턴스(t3.micro 등)는 제한이 100개 미만으로 매우 낮아 약간의 트래픽만 튀어도 쉽게 발생하므로 파라미터 설정을 변경하거나 스케일업해야 합니다.

📌 4세션 핵심 요약: 무작정 설정 임계치만 올리면 서버 전체가 붕괴됩니다. 백엔드의 커넥션 풀 스케일과 DB 최대 한도의 조화를 맞추고, 코드 단의 자원 누수를 완벽히 차단하는 것이 정석입니다.

5. 핵심 요약 및 마치며

  • Too many connections는 DB의 최대 허용 연결 수치가 초과하여 생기는 자원 고갈 장애입니다.
  • 해결을 위해 SHOW PROCESSLIST로 좀비 제거 ➡️ cnf 설정 파일에서 max_connections 및 타임아웃 최적화 ➡️ 서비스 재시작 단계를 거쳐야 합니다.
  • 근본적으로는 소스코드 내부에서 DB 세션 반환이 누수(Connection Leak)되고 있는지 전수 조사해야 합니다.

데이터베이스는 서비스의 심장입니다. 커넥션 메커니즘을 명확히 제어할 수 있을 때, 대규모 트래픽 앞에서도 무너지지 않는 견고한 서비스를 완성할 수 있습니다.


댓글 남기기

sys-hack에서 더 알아보기

지금 구독하여 계속 읽고 전체 아카이브에 액세스하세요.

계속 읽기