MySQL 접속(커넥션) 부하를 줄이는 방법

① “접속 자체를 줄이기”,
② “접속 비용을 싸게 만들기”,
③ “접속이 몰려도 버티게 하기” 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가 감당 가능한 범위로 설계
  • 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) 가장 흔한 “즉시 효과” 조합

  1. 앱 커넥션 풀 적용 + 풀 크기 상한 설정
  2. 캐시(특히 설정/코드/상태성 조회) 도입
  3. N+1 제거 / 배치화
  4. 필요 시 읽기 레플리카 + 라우팅 또는 ProxySQL

원하시면 **현재 구조(언어/프레임워크, 앱 인스턴스 개수, 현재 max_connections, 평균 QPS/피크 QPS, “매 요청 새 연결인지”)**만 알려주면, “풀 크기 산정”과 “우선순위 조치 5개”를 딱 맞게 잡아드릴게요.

DB max_connections 10으로 제어 하는 방법

MySQL에서 **동시 접속을 10개로 “강제”**하려면 핵심은 max_connections=10 설정입니다. (그리고 관리자/모니터링용 여유도 같이 고려해야 합니다)

1) 즉시(재시작 없이) 10으로 바꾸기

관리자 권한으로 실행:

  • 즉시 적용됩니다.
  • MySQL 재시작하면 원래 값으로 돌아갈 수 있으니, 아래 “영구 적용”도 같이 해야 합니다.
  • 이미 10개 초과로 연결돼 있으면, 기존 연결은 유지되고 새 연결부터 제한됩니다.

현재 값 확인:

2) 영구 적용(재시작 후에도 유지)

MySQL 설정 파일에 넣고 재시작합니다.

Linux (대부분)

/etc/my.cnf 또는 /etc/mysql/my.cnf 또는 /etc/mysql/mysql.conf.d/mysqld.cnf

Windows

my.ini 또는 my.cnf (보통 MySQL 설치 폴더 또는 ProgramData)

적용 후 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) 설정 확인/모니터링 명령

현재 접속 수:

프로세스 목록:


주의 (운영에서 흔히 터지는 문제)

  • 앱 서버가 2대 이상이면 각 서버가 풀 10개씩 잡아버려서 바로 막힙니다.
    → “전체 합계가 10”이 되게 설계해야 합니다.
  • 커넥션을 매번 새로 생성하는 코드가 있으면 Too many connections가 급증합니다. 풀링 필수.