카테고리 : MySQL/기술노트

connection timeout 변수 정리: wait_timeout, interactive_timeout, net_read_timeout, net_write_timeout

MySQL에서 wait_timeout, interactive_timeout, net_read_timeout, net_write_timeout가 각각 무엇을 보호하며 어떤 장애 양상으로 나타나는지 운영 관점에서 정리한다.

저자: MySQL 기술 노트 작성: 2026.06.21 약 13분 7,638자
다운로드

1. 왜 connection timeout 변수를 구분해서 이해해야 하는가

운영 현장에서 애플리케이션이 MySQL server has gone away, Lost connection to MySQL server during query, Aborted connection, Communications link failure 같은 오류를 내면 많은 팀이 이를 한 덩어리의 “DB timeout 문제”로 묶어 버린다. 그러나 실제로는 어느 단계에서 연결이 멈췄는가에 따라 원인과 대응이 완전히 달라진다.

  • 오랫동안 놀고 있던 세션이 갑자기 끊겼다면 wait_timeout 계열을 먼저 의심해야 한다.
  • 대화형 클라이언트와 배치/애플리케이션 세션의 idle 정책이 다르다면 interactive_timeout 해석이 필요하다.
  • 클라이언트가 요청 본문을 너무 천천히 보내는 경우에는 net_read_timeout이 더 직접적인 보호 장치다.
  • 서버가 큰 결과를 보내는데 클라이언트가 충분히 읽지 못하면 net_write_timeout이 문제의 핵심이 된다.

중요한 점은 이 변수들이 모두 “연결이 오래 걸린다”는 일반론을 다루는 것이 아니라, MySQL 서버가 특정 I/O 단계에서 얼마 동안 기다릴지를 각각 다르게 정의한다는 사실이다. 따라서 timeout 조정은 숫자 하나를 키우는 작업이 아니라, 세션의 수명주기와 애플리케이션 I/O 패턴을 분해해서 보는 작업이어야 한다.

또한 이 변수들은 TCP connect 자체의 시간 제한을 제어하지 않는다. 즉, 애플리케이션이 DB에 처음 붙을 때의 connect timeout, DNS 지연, 방화벽/NAT idle timeout, 프록시의 upstream timeout, JDBC/socket timeout은 별도의 계층이다. 이 구분이 없으면 MySQL 변수를 올려도 증상이 그대로 남는다.

2. 네 변수의 역할을 먼저 한 문장으로 정리하면

운영자가 빠르게 판단할 수 있도록 먼저 핵심 정의를 한 줄씩 고정해 두는 편이 좋다.

  • wait_timeout: 비대화형(non-interactive) 세션이 아무 명령도 보내지 않고 idle 상태로 머물 때 서버가 연결을 유지하는 최대 시간
  • interactive_timeout: interactive client로 분류되는 세션의 idle 유지 시간 기본값
  • net_read_timeout: 서버가 클라이언트로부터 다음 패킷 조각을 읽는 동안 기다리는 최대 시간
  • net_write_timeout: 서버가 클라이언트에게 결과를 쓰는 동안 클라이언트가 충분히 읽어 가지 않을 때 기다리는 최대 시간

여기서 즉시 확인해야 할 중요한 차이가 있다.

  1. wait_timeoutinteractive_timeoutidle 세션 수명 정책에 가깝다.
  2. net_read_timeoutnet_write_timeout활성 I/O 중 지연 보호 장치에 가깝다.
  3. 긴 쿼리가 실행 중이라고 해서 wait_timeout이 그 쿼리를 중간에 끊는 것은 아니다.
  4. 쿼리 자체는 빠르더라도, 느린 네트워크/느린 클라이언트/부분 전송 상태 때문에 net_*_timeout 문제가 발생할 수 있다.

즉, “연결 timeout”이라는 같은 이름 아래에 있지만 보호 대상이 다르다.

3. 내부 동작 원리: MySQL은 어느 순간에 어떤 timeout을 본는가

MySQL 서버는 연결을 받아들인 뒤 세션을 유지하고, 명령을 읽고, 결과를 쓰는 과정을 반복한다. timeout 변수를 이해하려면 이 흐름 위에 각 변수가 어디에 걸리는지를 먼저 그려 보는 것이 가장 정확하다.

flowchart TD
    A[클라이언트 연결 성립] --> B[세션 생성 및 초기화]
    B --> C{interactive client 인가}
    C -- 예 --> D[session wait_timeout 초기값에 interactive_timeout 반영 가능]
    C -- 아니오 --> E[session wait_timeout 초기값에 wait_timeout 반영]
    D --> F[명령 대기 idle 상태]
    E --> F
    F -->|idle 시간 초과| G[서버가 세션 종료]
    F -->|클라이언트가 명령 전송 시작| H[서버가 요청 패킷 읽기]
    H -->|읽기 지연 장기화| I[net_read_timeout 초과]
    H -->|정상 수신| J[쿼리 실행]
    J --> K[결과 전송]
    K -->|클라이언트가 느리게 읽음| L[net_write_timeout 초과]
    K -->|전송 완료| F

이 흐름을 운영 언어로 바꾸면 다음과 같다.

3.1 세션이 아무것도 하지 않을 때는 wait_timeout 계열이 적용된다

클라이언트가 인증을 끝내고 세션을 만든 뒤, 일정 시간 동안 아무 명령도 보내지 않으면 서버는 그 연결이 더 이상 유용하지 않다고 판단할 수 있다. 이때 기준이 되는 값이 wait_timeout이다. 다만 interactive client로 분류된 세션은 시작 시점에 interactive_timeout 값을 session wait_timeout 초기값으로 사용할 수 있다.

실무적으로는 최종적으로 세션이 idle 상태에서 얼마나 오래 살아 있는가를 볼 때 @@session.wait_timeout이 더 직접적인 숫자다. interactive_timeout은 “어떤 세션이 session wait_timeout을 어떤 초기값으로 받았는가”에 가까운 의미를 가진다.

3.2 클라이언트가 요청을 너무 천천히 보내면 net_read_timeout이 개입한다

대용량 INSERT 본문, 큰 multi-value statement, 느린 WAN 구간, 프록시 병목, 비정상 connector 버그가 있으면 클라이언트가 MySQL 서버로 요청 패킷을 한 번에 밀어 넣지 못할 수 있다. 서버는 다음 패킷 조각을 계속 기다리다가 한도를 넘기면 연결을 실패 처리한다. 이때 핵심은 idle 세션이 아니라 진행 중인 읽기 작업이라는 점이다.

3.3 서버가 결과를 보내는데 클라이언트가 읽지 못하면 net_write_timeout이 개입한다

대규모 SELECT 결과를 매우 느린 애플리케이션 소비자가 읽거나, 네트워크가 정체되거나, 중간 프록시가 backpressure를 유발하면 서버의 쓰기 작업이 오래 막힐 수 있다. 이때는 쿼리 엔진이 느린 것이 아니라 결과 전달 단계가 느린 것이다. 운영자가 이를 SQL 튜닝 문제로 오판하면 시간만 낭비한다.

4. wait_timeoutinteractive_timeout: idle 세션 정책의 핵심

이 두 변수는 이름이 비슷해 자주 혼동되지만, 실제 운영 해석은 다음처럼 잡는 편이 명확하다.

4.1 wait_timeout은 대부분의 애플리케이션 세션에서 직접 체감되는 값이다

일반적인 애플리케이션 드라이버, connection pool, 배치 프로세스는 interactive client로 취급되지 않는 경우가 많다. 이때 idle 세션이 얼마나 오래 유지되는지는 사실상 wait_timeout이 결정한다. 따라서 서버에서 너무 짧게 잡으면 다음 현상이 나타난다.

  • pool 안에서 놀고 있던 연결이 재사용 시점에 이미 끊겨 있음
  • 첫 쿼리에서 server has gone away 또는 reconnect 비용이 발생함
  • 애플리케이션이 죽은 연결을 빠르게 감지하지 못하면 요청 지연이 증가함
  • 장애 조치 후 connection storm와 결합되어 재연결 폭주가 발생함

반대로 너무 길게 잡으면 문제가 사라지는 것이 아니라 다른 리스크가 생긴다.

  • 사용하지 않는 세션이 오래 남아 Threads_connected가 불필요하게 높아질 수 있다.
  • pool 누수나 세션 해제 누락이 가려진다.
  • 프록시/NAT/LB의 더 짧은 idle timeout과 어긋나면, DB는 살아 있다고 생각하지만 중간 네트워크는 이미 세션을 버린 상태가 될 수 있다.

4.2 interactive_timeout은 mysql CLI 같은 대화형 세션의 기본 idle 정책에 가깝다

운영자가 터미널에서 mysql 클라이언트로 접속해 잠시 생각하다가 다시 쿼리를 날리는 상황은 애플리케이션 커넥션 풀과 성격이 다르다. 이때 더 긴 idle 시간을 주고 싶다면 interactive_timeout이 의미를 가진다. 다만 실무에서 중요한 포인트는, 애플리케이션이 정말 interactive client로 연결하는지 막연히 가정하지 말아야 한다는 것이다.

많은 팀이 interactive_timeout만 길게 올리고 애플리케이션 disconnect 문제를 해결했다고 생각하지만, 실제 세션은 non-interactive라 아무 효과가 없는 경우가 있다. 문제 분석 시에는 반드시 @@session.wait_timeout을 실제 세션에서 확인해야 한다.

4.3 긴 쿼리와 idle timeout은 다른 문제다

자주 나오는 오해 중 하나는 “배치 쿼리가 10분 걸리니 wait_timeout을 600보다 크게 올려야 한다”는 식의 판단이다. 그러나 쿼리가 실행 중이면 세션은 idle이 아니다. wait_timeout은 아무 명령도 오가지 않는 대기 상태에 더 직접적으로 적용된다. 긴 실행 시간을 제어하려면 statement timeout 계열, 애플리케이션 socket timeout, 리소스 경합, 실행 계획 문제를 따로 봐야 한다.

5. net_read_timeoutnet_write_timeout: 느린 네트워크와 느린 소비자를 구분하는 기준

운영 현장에서 이 둘은 상대적으로 덜 알려져 있지만, 실제 장애 구분에는 매우 중요하다.

5.1 net_read_timeout이 의미하는 것은 “다음 바이트를 얼마나 기다릴 것인가”이다

클라이언트가 요청을 시작했지만 패킷이 끊겨 들어오거나 중간에 멈추면 서버는 계속 기다릴 수 없다. 특히 다음 상황에서 의미가 커진다.

  • 대용량 INSERT 또는 LOAD DATA 계열 작업
  • 지연이 큰 네트워크 구간을 통과하는 클라이언트
  • 프록시/게이트웨이가 요청 스트림을 천천히 전달하는 구조
  • 비정상적인 드라이버 또는 애플리케이션 backpressure

이때 net_read_timeout을 무작정 키우면 일시적 증상은 줄 수 있지만, 느린 업스트림 문제를 숨길 수 있다. 먼저 네트워크 품질, 패킷 크기, 애플리케이션 flush 패턴, 프록시 타임아웃 정합성을 함께 확인해야 한다.

5.2 net_write_timeout은 “서버가 결과를 보내고 있는데 상대가 읽어 주지 않는다”는 신호다

운영자가 자주 놓치는 패턴은 DB가 느린 것이 아니라 클라이언트가 결과를 소비하지 못하는 상황이다. 예를 들어 다음과 같은 경우가 있다.

  • 애플리케이션이 매우 큰 result set을 한 줄씩 천천히 처리함
  • 배치 작업이 디스크/CPU 병목으로 소비 속도가 느림
  • 프록시가 downstream 압력을 받아 소켓 drain이 늦어짐
  • WAN 구간 품질이 낮아 결과 전송이 오래 걸림

이 상황에서 SQL만 튜닝해도 근본 해결이 되지 않는다. 결과 집합을 줄이거나 pagination/streaming 설계를 바꾸거나, 소비자 처리 속도와 네트워크 구조를 개선해야 한다.

5.3 큰 결과를 보내는 쿼리는 실행 시간이 아니라 전송 시간이 병목일 수 있다

특히 SELECT *로 대량 데이터를 내보내는 배치에서는 서버 내부 실행은 빠른데, 전송과 소비에 대부분의 시간이 쓰일 수 있다. 이때 slow query log만 보면 원인이 잘 드러나지 않을 수 있다. Performance Schema, 애플리케이션 소비 속도, 네트워크 RTT, 프록시 지표를 함께 봐야 한다.

6. 운영 관점 해석: 어디에서 숫자를 맞춰야 하는가

timeout 튜닝은 변수 하나를 절대값으로 정하는 문제가 아니라, 가장 짧은 타이머가 실제 세션 수명을 결정한다는 사실에서 출발해야 한다.

6.1 Connection pool idle 정책이 wait_timeout보다 짧아야 한다

애플리케이션이 idle connection을 30분 보관하는데 서버의 wait_timeout이 10분이면, pool은 살아 있다고 믿는 연결을 DB는 이미 정리했을 수 있다. 이 불일치는 요청 첫 사용 시점의 오류로 나타난다. 따라서 일반적으로는 다음 원칙이 안전하다.

  • 애플리케이션 pool max idle time < DB wait_timeout
  • 중간 프록시/NAT/LB idle timeout도 함께 고려
  • keepalive 또는 validation query 정책을 명확히 함

6.2 너무 긴 wait_timeout은 연결 누수와 과대 pool을 숨긴다

idle 연결이 많아도 당장 CPU가 낮을 수 있으므로 문제를 체감하지 못할 수 있다. 그러나 failover, 재배포, 네트워크 flap 이후에는 오래 쌓인 pool과 재연결 폭주가 결합해 더 큰 장애를 만들 수 있다. 따라서 wait_timeout은 “불편하지 않을 만큼 길게”가 아니라, 애플리케이션 재사용 정책과 관측 체계가 허용하는 범위 안에서 필요 이상 길지 않게 잡아야 한다.

6.3 net_*_timeout을 늘리기 전에 정말 네트워크/소비자 문제인지 확인해야 한다

MySQL 쪽 timeout을 늘렸더니 에러가 줄었다고 해서 해결이 끝난 것은 아니다. 프록시 buffer 고갈, 애플리케이션 소비 지연, WAN 손실률, oversized packet, 비효율적인 대량 fetch가 근본 원인일 수 있다. 이런 경우 timeout 완화는 장애를 뒤로 미루는 조치일 뿐이다.

7. Aurora MySQL과 관리형 환경에서의 차이

Aurora MySQL이나 RDS MySQL에서는 timeout 해석에 몇 가지 추가 층이 있다.

7.1 실제 세션 수명은 DB 변수만으로 결정되지 않는다

관리형 환경에서는 애플리케이션과 DB 사이에 다음 계층이 추가될 수 있다.

  • RDS Proxy
  • NAT Gateway 또는 VPC 경계 장비
  • Kubernetes ingress/sidecar/proxy
  • 애플리케이션 프레임워크의 pool 및 socket timeout

이 중 어느 한 계층의 idle timeout이 더 짧으면, 실질적인 연결 수명은 MySQL 변수보다 그 값에 의해 먼저 잘린다. 따라서 Aurora에서 disconnect 이슈가 보인다고 해서 곧바로 wait_timeout부터 올리는 것은 위험하다.

7.2 Failover 이후의 증상은 idle timeout 문제가 아닐 수 있다

Aurora writer failover 이후의 연결 오류는 세션이 idle이어서 끊긴 것이 아니라, endpoint 전환·TCP reset·in-flight transaction 중단·pool 재연결 폭주 때문에 나타나는 경우가 많다. 이때 필요한 대응은 다음에 가깝다.

  • 재시도 backoff와 jitter 적용
  • pool warm-up 속도 제어
  • RDS Proxy 사용 검토
  • stale connection 검출 로직 정비

즉, failover 직후 오류를 전부 wait_timeout 문제로 분류하면 진단이 어긋난다.

7.3 Parameter group 변경 가능 여부와 적용 범위를 구분해야 한다

Aurora/RDS에서는 같은 변수라도 동적 적용 여부, cluster/instance parameter group 범위, 즉시 반영 여부가 다를 수 있다. 운영 변경 시에는 “문서상 dynamic인가”뿐 아니라 해당 배포 모델에서 어떤 레벨에 적용되고 어떤 인스턴스가 언제 새 값을 받는가를 반드시 함께 확인해야 한다.

8. 먼저 실행해 볼 기본 점검 SQL

다음 SQL은 현재 서버의 timeout 변수와 연결 상태를 빠르게 읽는 가장 기본적인 점검 예제다.

SELECT VERSION() AS mysql_version;

SHOW VARIABLES
WHERE Variable_name IN (
  'wait_timeout',
  'interactive_timeout',
  'net_read_timeout',
  'net_write_timeout'
);

SHOW GLOBAL STATUS
WHERE Variable_name IN (
  'Aborted_clients',
  'Aborted_connects',
  'Connections',
  'Threads_connected',
  'Threads_running'
);

실행 결과(MySQL 8.0.46):

mysql> SELECT VERSION() AS mysql_version;

+---------------+
| mysql_version |
+---------------+
| 8.0.46        |
+---------------+
1 row in set (0.00 sec)

mysql> SHOW VARIABLES
    -> WHERE Variable_name IN (
    ->   'wait_timeout',
    ->   'interactive_timeout',
    ->   'net_read_timeout',
    ->   'net_write_timeout'
    -> );

+---------------------+-------+
| Variable_name       | Value |
+---------------------+-------+
| interactive_timeout | 28800 |
| net_read_timeout    | 30    |
| net_write_timeout   | 60    |
| wait_timeout        | 28800 |
+---------------------+-------+
4 rows in set (0.01 sec)

mysql> SHOW GLOBAL STATUS
    -> WHERE Variable_name IN (
    ->   'Aborted_clients',
    ->   'Aborted_connects',
    ->   'Connections',
    ->   'Threads_connected',
    ->   'Threads_running'
    -> );

+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Aborted_clients   | 0     |
| Aborted_connects  | 0     |
| Connections       | 11    |
| Threads_connected | 1     |
| Threads_running   | 2     |
+-------------------+-------+
5 rows in set (0.00 sec)

이 결과를 읽을 때의 포인트는 다음과 같다.

  • timeout 변수의 현재 전역값이 무엇인가
  • Aborted_clients가 증가하고 있는가
  • 현재 활성 연결 수와 실행 중 thread 수가 얼마나 되는가
  • disconnect 문제가 인증 실패인지, idle close인지, 네트워크 I/O 문제인지 추가 조사 방향을 잡을 수 있는가

9. Session 수준 변경이 실제로 어떻게 반영되는지 확인하는 예제

운영 중 전역값을 바로 바꾸기 전에, 테스트 세션에서 session 값을 바꿔 동작 가정을 검증하는 습관이 좋다.

SELECT @@session.wait_timeout AS before_wait_timeout,
       @@session.net_read_timeout AS before_net_read_timeout,
       @@session.net_write_timeout AS before_net_write_timeout;

SET SESSION wait_timeout = 30;
SET SESSION net_read_timeout = 45;
SET SESSION net_write_timeout = 45;

SELECT @@session.wait_timeout AS after_wait_timeout,
       @@session.net_read_timeout AS after_net_read_timeout,
       @@session.net_write_timeout AS after_net_write_timeout;

실행 결과(MySQL 8.0.46):

mysql> SELECT @@session.wait_timeout AS before_wait_timeout,
    ->        @@session.net_read_timeout AS before_net_read_timeout,
    ->        @@session.net_write_timeout AS before_net_write_timeout;

+---------------------+-------------------------+--------------------------+
| before_wait_timeout | before_net_read_timeout | before_net_write_timeout |
+---------------------+-------------------------+--------------------------+
|               28800 |                      30 |                       60 |
+---------------------+-------------------------+--------------------------+
1 row in set (0.00 sec)

mysql> SET SESSION wait_timeout = 30;

Query OK, 0 rows affected (0.00 sec)

mysql> SET SESSION net_read_timeout = 45;

Query OK, 0 rows affected (0.00 sec)

mysql> SET SESSION net_write_timeout = 45;

Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @@session.wait_timeout AS after_wait_timeout,
    ->        @@session.net_read_timeout AS after_net_read_timeout,
    ->        @@session.net_write_timeout AS after_net_write_timeout;

+--------------------+------------------------+-------------------------+
| after_wait_timeout | after_net_read_timeout | after_net_write_timeout |
+--------------------+------------------------+-------------------------+
|                 30 |                     45 |                      45 |
+--------------------+------------------------+-------------------------+
1 row in set (0.00 sec)

이 예제는 세 가지 사실을 확인하는 용도로 유용하다.

  1. 세션 단위 조정이 가능한가
  2. 변경 후 실제 session 값이 기대대로 반영되는가
  3. 전역값 조정 없이도 애플리케이션/세션별 정책 테스트가 가능한가

단, interactive_timeout은 현재 세션이 interactive로 생성되었는지 여부와 초기값 반영 맥락이 중요하므로, 단순히 session 변수 몇 개를 바꾸는 테스트와는 의미가 다를 수 있다.

10. 현재 foreground 세션을 관찰하는 보조 진단 예제

다음 쿼리는 지금 서버에 보이는 foreground 세션의 기본 상태를 확인하는 데 유용하다. 단일 테스트 컨테이너에서는 결과가 단순할 수 있지만, 운영 환경에서는 idle 세션이 많은지, 어떤 command 상태가 많은지 빠르게 훑는 출발점이 된다.

SELECT PROCESSLIST_ID,
       PROCESSLIST_USER,
       PROCESSLIST_HOST,
       PROCESSLIST_COMMAND,
       PROCESSLIST_TIME,
       PROCESSLIST_STATE
FROM performance_schema.threads
WHERE TYPE = 'FOREGROUND'
  AND PROCESSLIST_ID IS NOT NULL
ORDER BY PROCESSLIST_TIME DESC
LIMIT 10;

실행 결과(MySQL 8.0.46):

mysql> SELECT PROCESSLIST_ID,
    ->        PROCESSLIST_USER,
    ->        PROCESSLIST_HOST,
    ->        PROCESSLIST_COMMAND,
    ->        PROCESSLIST_TIME,
    ->        PROCESSLIST_STATE
    -> FROM performance_schema.threads
    -> WHERE TYPE = 'FOREGROUND'
    ->   AND PROCESSLIST_ID IS NOT NULL
    -> ORDER BY PROCESSLIST_TIME DESC
    -> LIMIT 10;

+----------------+------------------+------------------+---------------------+------------------+------------------------+
| PROCESSLIST_ID | PROCESSLIST_USER | PROCESSLIST_HOST | PROCESSLIST_COMMAND | PROCESSLIST_TIME | PROCESSLIST_STATE      |
+----------------+------------------+------------------+---------------------+------------------+------------------------+
|              5 | event_scheduler  | localhost        | Daemon              |                5 | Waiting on empty queue |
|              7 | NULL             | NULL             | Daemon              |                5 | Suspending             |
|             13 | root             | localhost        | Query               |                0 | executing              |
+----------------+------------------+------------------+---------------------+------------------+------------------------+
3 rows in set (0.00 sec)

이 결과만으로 timeout 문제를 확정할 수는 없다. 그러나 다음 같은 판단에 도움을 준다.

  • idle 세션이 대량으로 방치되는 패턴이 있는가
  • Sleep 세션이 비정상적으로 오래 쌓이는가
  • 특정 애플리케이션 사용자나 host가 연결을 많이 붙잡고 있는가

11. 자주 발생하는 오해와 장애 패턴

11.1 wait_timeout을 늘리면 모든 disconnect가 해결된다는 오해

실제 운영에서는 중간 프록시가 먼저 세션을 정리하거나, 애플리케이션 socket timeout이 더 짧거나, 네트워크 재전송 문제로 net_read_timeout/net_write_timeout이 먼저 발생하는 경우가 흔하다. 따라서 wait_timeout 증가는 가장 마지막 조정 항목이어야 한다.

11.2 긴 배치 쿼리가 끊겼으니 wait_timeout 문제라는 오해

배치가 정말 idle 상태였는지, 아니면 결과 전송/소비가 느렸는지 구분해야 한다. 대용량 export 작업은 net_write_timeout 쪽이 더 직접적일 수 있다.

11.3 pool validation 없이 긴 idle을 허용하는 실수

connection pool이 idle 연결을 오래 보관할수록 validation query 또는 borrow 시 connection check가 더 중요해진다. 그렇지 않으면 죽은 세션을 실제 트래픽 시점에야 발견하게 된다.

11.4 timeout 수치를 크게 잡아 장애를 숨기는 실수

짧은 timeout이 증상을 빨리 드러내는 경우도 있다. 예를 들어 비정상적으로 느린 업스트림, result 소비 병목, pool 누수는 timeout을 길게 늘릴수록 더 늦게 발견될 수 있다. 운영자는 “에러 감소”와 “문제 해결”을 구분해야 한다.

12. 실무 체크리스트

  • 애플리케이션 pool idle timeout이 wait_timeout
  • interactive_timeout
  • Aborted_clients, Aborted_connects, Threads_connected

13. 결론

wait_timeout, interactive_timeout, net_read_timeout, net_write_timeout은 모두 연결 안정성을 다루지만, 실제로는 idle 세션 관리, interactive 세션의 기본 정책, 요청 읽기 지연 보호, 결과 쓰기 지연 보호라는 서로 다른 층을 담당한다. 이 차이를 구분하지 않으면 운영자는 SQL 성능 문제를 네트워크 문제로 오판하거나, 프록시 timeout 문제를 MySQL 변수로 덮으려 하거나, 애플리케이션 pool 설계 오류를 DB 설정으로 숨기게 된다.

실무에서 가장 중요한 원칙은 단순하다. 먼저 어느 단계에서 연결이 멈추는지를 분류하고, 그 다음에 해당 timeout을 조정해야 한다. 다음 글에서는 이 timeout 정책이 connection pool 설계, max_connections, 재접속 폭주 억제와 어떻게 맞물리는지 더 구체적으로 이어서 다룰 수 있다.