① “접속 자체를 줄이기”,
② “접속 비용을 싸게 만들기”,
③ “접속이 몰려도 버티게 하기” 3갈래로 정리하면 됩니다.
1) 접속 자체를 줄이기 (가장 효과 큼)
- Connection Pooling 사용
매 요청마다 새로 연결하지 말고, 앱에서 풀로 재사용하세요. (Java HikariCP, .NET/MySqlConnector pooling, Node mysql2 pool 등) - 트래픽/조회 캐싱
- 앱 레벨 캐시(메모리/Redis)로 “자주 조회되는 데이터”를 DB까지 안 가게 만들기
- 결과 캐시(예: 인기 상품, 공지, 코드 테이블, 설정값)
- 읽기 트래픽 분리(읽기 복제본/리드 레플리카)
- 읽기 쿼리는 replica로, 쓰기는 primary로 라우팅
- 불필요한 “짧은 쿼리 다건”을 “한 번의 쿼리”로
- N+1 문제 제거 (IN, JOIN, batch fetch)
- HTTP keep-alive / gRPC 등과 별개로, DB는 “요청당 1커넥션” 패턴을 피하기
- 특히 PHP/CGI처럼 프로세스 모델에 따라 커넥션이 폭증하기 쉬움 → PHP-FPM 설정과 풀링/퍼시스턴트 커넥션 점검
2) 접속 비용을 싸게 만들기
- DNS/네트워크 지연 최소화
- 앱과 DB를 같은 VPC/서브넷/리전에 두기 (왕복 지연이 커넥션 비용을 키움)
- TLS(SSL) 사용 시
- “매번 핸드셰이크”가 일어나지 않게 풀링 필수
- 가능하면 앱↔DB 사이 전용망이면 TLS 정책을 현실적으로 설계
- 인증 플러그인/설정 점검
- 불필요하게 무거운 인증/플러그인이면 교체 고려(환경에 따라)
- Prepared Statement 재사용
- 드라이버/풀에서 서버사이드 prepared 재사용이 되면 CPU/파싱 비용 절감
3) 접속이 몰려도 버티게 하기 (서버/설정/아키텍처)
- max_connections 무작정 올리기 금지
- 많이 열리면 메모리/스레드 컨텍스트 스위칭으로 더 느려질 수 있음
- 먼저 “풀 크기 제한 + 대기큐”로 제어하는 게 안전
- 앱 풀 크기(중요)
- 예: 앱 인스턴스 10개 × 풀 50 = 잠재 500 커넥션
DB max_connections 300이면 폭주/에러 발생
→ (앱 인스턴스 수 × 풀 크기) ≤ DB가 감당 가능한 범위로 설계
- 예: 앱 인스턴스 10개 × 풀 50 = 잠재 500 커넥션
- Thread Pool/Buffer 튜닝(대표적으로 InnoDB)
innodb_buffer_pool_size를 충분히(서버 RAM의 큰 비중) 잡으면 디스크 I/O가 줄어 “커넥션당 체감 부하”가 감소
- Proxy 계층 도입
- ProxySQL / MySQL Router로 커넥션 멀티플렉싱, 읽기/쓰기 분리, 쿼리 라우팅, 제한/큐잉 가능
- 커넥션 폭주 방지(백프레셔)
- 앱에서 DB 타임아웃을 너무 길게 두면 “느려질수록 더 몰림” (스노우볼)
- 짧은 타임아웃 + 재시도 정책(지수 백오프) + 서킷브레이커가 접속 폭주를 막음
4) 운영에서 바로 확인할 것(진단 체크리스트)
- 현재 커넥션 상태
Threads_connected,Threads_running, 커넥션 생성/폐기 빈도
- “커넥션 생성이 병목인지” 확인
- “초당 커넥션 생성”이 높은데 실제 쿼리는 가볍다면 → 풀링 미적용/오작동 가능성 큼
- 슬로우 쿼리
- 쿼리가 느리면 커넥션이 오래 잡혀서
Threads_running이 올라가고 결과적으로 접속 부하로 보입니다
- 쿼리가 느리면 커넥션이 오래 잡혀서
- 에러 패턴
Too many connections,Connect timeout,Aborted_connects증가 여부
5) 가장 흔한 “즉시 효과” 조합
- 앱 커넥션 풀 적용 + 풀 크기 상한 설정
- 캐시(특히 설정/코드/상태성 조회) 도입
- N+1 제거 / 배치화
- 필요 시 읽기 레플리카 + 라우팅 또는 ProxySQL
원하시면 **현재 구조(언어/프레임워크, 앱 인스턴스 개수, 현재 max_connections, 평균 QPS/피크 QPS, “매 요청 새 연결인지”)**만 알려주면, “풀 크기 산정”과 “우선순위 조치 5개”를 딱 맞게 잡아드릴게요.
DB max_connections 10으로 제어 하는 방법
MySQL에서 **동시 접속을 10개로 “강제”**하려면 핵심은 max_connections=10 설정입니다. (그리고 관리자/모니터링용 여유도 같이 고려해야 합니다)
1) 즉시(재시작 없이) 10으로 바꾸기
관리자 권한으로 실행:
|
1 2 3 4 |
SET GLOBAL max_connections = 10; |
- 즉시 적용됩니다.
- MySQL 재시작하면 원래 값으로 돌아갈 수 있으니, 아래 “영구 적용”도 같이 해야 합니다.
- 이미 10개 초과로 연결돼 있으면, 기존 연결은 유지되고 새 연결부터 제한됩니다.
현재 값 확인:
|
1 2 3 4 |
SHOW VARIABLES LIKE 'max_connections'; |
2) 영구 적용(재시작 후에도 유지)
MySQL 설정 파일에 넣고 재시작합니다.
Linux (대부분)
/etc/my.cnf 또는 /etc/mysql/my.cnf 또는 /etc/mysql/mysql.conf.d/mysqld.cnf
|
1 2 3 4 5 |
-mysqld- max_connections = 10 |
Windows
my.ini 또는 my.cnf (보통 MySQL 설치 폴더 또는 ProgramData)
|
1 2 3 4 5 |
-mysqld- max_connections = 10 |
적용 후 MySQL 재시작 필요.
3) “관리자 접속도 막히는” 사고 방지 (강력 추천)
max_connections=10으로 너무 낮게 잡으면, 앱 접속이 10개를 다 먹었을 때 DBA가 로그인도 못 하는 상황이 생길 수 있습니다.
그래서 보통 다음도 같이 봅니다.
(A) 관리자용 예비 커넥션
MySQL은 extra_max_connections(버전에 따라) / 또는 max_connections 외에 관리자 접속을 위한 별도 슬롯 개념이 제한적이라,
현실적으로는:
- 앱 풀을 8~9로 제한하고
- DB
max_connections는 10~20 정도로 두는 방식이 안전합니다.
(B) 앱에서 커넥션 풀 상한을 10보다 더 작게
DB를 10으로 막는 것만으로는 “폭주”가 사라지지 않고 에러만 늘 수 있어요.
앱 쪽 풀도 같이 제한해야 합니다. (예: 인스턴스가 여러 개면 합계가 10을 넘으면 바로 초과)
4) 설정 확인/모니터링 명령
현재 접속 수:
|
1 2 3 4 5 |
SHOW GLOBAL STATUS LIKE 'Threads_connected'; SHOW GLOBAL STATUS LIKE 'Max_used_connections'; |
프로세스 목록:
|
1 2 3 4 |
SHOW PROCESSLIST; |
주의 (운영에서 흔히 터지는 문제)
- 앱 서버가 2대 이상이면 각 서버가 풀 10개씩 잡아버려서 바로 막힙니다.
→ “전체 합계가 10”이 되게 설계해야 합니다. - 커넥션을 매번 새로 생성하는 코드가 있으면
Too many connections가 급증합니다. 풀링 필수.
