PostgreSQL
PostgreSQL: timeout 관련 파라미터
dewstream
2024. 12. 28. 21:00
※ Timeout-related Parameters in PostgreSQL.
※ Version: PostgreSQL 16.
안녕하세요. 듀스트림입니다.
PostgreSQL은 약 400개 정도의 파라미터를 설정 가능하도록 설계되어 있습니다.
오늘은 가장 많이 사용하는 카테고리 중 하나인 timeout 관련 파라미터를 살펴보겠습니다.
statement_timeout
- SQL 쿼리 실행에 허용된 최대 시간을 설정합니다. 초과 시 쿼리가 자동으로 중단됩니다.
- 타임아웃은 명령이 서버에 도착한 시점부터 서버에서 완료될 때까지 측정됩니다.
- 단순 쿼리 메시지에 여러 SQL 문이 포함된 경우, 타임아웃은 각 문에 개별적으로 적용됩니다.
- 쿼리 관련 메시지(예: Parse, Bind, Execute, Describe)가 도착하면 타임아웃이 시작됩니다.
- Execute 또는 Sync 메시지가 완료되면 타임아웃이 취소됩니다.
- 모든 세션에 영향을 미치기 때문에 postgresql.conf에서 statement_timeout을 설정하는 것은 권장되지 않습니다.
• 디폴트 값: 0(비활성화)
• 적용 가능 값: 0 ~ 정수값
• 예시:
-- 쿼리가 오래 걸리는 경우 서버를 과부하 상태로 만들지 않도록 제한 시간 설정
SET statement_timeout = '600s'; -- 600초 동안 완료되지 않으면 쿼리 중단
lock_timeout
- 테이블, 인덱스, 행 또는 기타 데이터베이스 객체에 대해 잠금을 시도하는 동안 지정된 시간 이상 대기하는 SQL 문을 중단합니다.
- 간 제한은 각 잠금 획득 시도에 개별적으로 적용됩니다.
- 이 제한은 명시적 잠금 요청(LOCK TABLE 또는 SELECT FOR UPDATE와 같은 NOWAIT 없이 실행된 경우)과 암묵적으로 획득된 잠금 모두에 적용됩니다.
- statement_timeout과 달리, 이 타임아웃은 잠금을 대기하는 동안에만 발생할 수 있습니다.
- statement_timeout이 0이 아닌 경우, lock_timeout을 동일하거나 더 큰 값으로 설정하는 것은 실효성이 없으며, 항상 statement_timeout이 먼저 발생합니다.
• 디폴트 값: 0(비활성화)
• 적용 가능 값: 0 ~ 정수값
• 예시:
-- 경합이 심한 환경에서 대기 시간을 제한
-- 동시성 문제로 인해 특정 세션이 잠금을 기다리며 지연되는 것을 방지
SET lock_timeout = '3s'; -- 3초 이상 잠금을 기다리면 에러 반환
idle_in_transaction_session_timeout
- 열린 트랜잭션 내에서 지정된 시간 이상 idle(유휴) 상태(클라이언트 쿼리를 기다리는 상태)에 있는 세션을 종료합니다.
- 트랜잭션이 열려 있는 상태로 세션이 idle 상태가 되면 아래와 같은 문제가 발생할 수 있습니다.
- 트랜잭션이 끝나지 않은 상태에서는 해당 테이블(데이터)의 잠금이 해제되지 않습니다.
예를 들어, 트랜잭션 내에서 데이터를 수정했지만 COMMIT이나 ROLLBACK을 호출하지 않은 상태로 세션이 멈춰 있다면, 해당 테이블(데이터)에 락이 걸린 상태로 유지됩니다.
다른 트랜잭션은 이 락이 해제될 때까지 대기해야 하므로 성능 저하나 교착 상태(deadlock)가 발생할 수 있습니다. - Vacuum 지연 및 테이블 Bloat이 발생합니다.
열린 트랜잭션에서는 PostgreSQL의 MVCC(Multi-Version Concurrency Control) 특성상 최근 삭제되거나 수정된 튜플(레코드)을 "활성 상태(Live Tuple)"로 간주합니다.
이런 상태에서는 PostgreSQL이 삭제된 튜플을 제거하는 VACUUM 작업을 수행할 수 없습니다. 결과적으로 테이블이 불필요하게 커지고 성능 저하를 유발합니다.
- 트랜잭션이 끝나지 않은 상태에서는 해당 테이블(데이터)의 잠금이 해제되지 않습니다.
• 디폴트 값: 0(비활성화)
• 적용 가능 값: 0 ~ 정수값
• 예시:
-- 오래된 트랜잭션으로 인한 리소스 잠금을 방지
-- 개발자가 트랜잭션을 완료하지 않고 대기 상태로 두는 실수를 방지
SET idle_in_transaction_session_timeout = '15min'; -- 15분 동안 idle 상태면 연결 종료
idle_session_timeout
- 열린 트랜잭션이 없는 상태에서 지정된 시간 이상 idle(유휴) 상태(클라이언트 쿼리를 기다리는 상태)에 있는 세션을 종료합니다.
- 기본적으로 유휴 세션은 서버에 큰 부하를 주지 않습니다.
- Connection-pooling 소프트웨어나 기타 미들웨어를 사용할 경우 설정하지 않는 것을 권고합니다.
- ALTER ROLE 명령을 사용하여 특정 사용자나 그룹에만 idle_session_timeout을 설정하는 것을 권고합니다.
- PostgreSQL은 유휴 상태의 세션도 하나의 연결로 간주하므로, max_connections 제한을 소모합니다.
• 디폴트 값: 0(비활성화)
• 적용 가능 값: 0 ~ 정수값
• 예시:
-- 오래된 비활성 연결로 인한 리소스 낭비 방지
SET idle_session_timeout = '15min'; -- 15분 동안 idle 상태면 세션 종료
ALTER ROLE <role_name> SET idle_session_timeout = '10min'; -- 10분 동안 idle 상태면 세션 종료
client_connection_check_interval
- 쿼리를 실행하는 동안 클라이언트가 여전히 연결되어 있는지 확인하는 선택적 검사의 간격을 설정합니다.
- 이 검사는 소켓을 폴링하여 수행되며, 커널이 연결이 끊어졌음을 보고할 경우 장시간 실행 중인 쿼리를 더 빨리 중단할 수 있도록 합니다.
- 이 옵션은 Linux, macOS, illumos 및 BSD 계열 운영 체제에서 제공되는 커널 이벤트에 의존하며, 현재 다른 시스템에서는 사용할 수 없습니다.
- 비활성화된 경우 서버는 소켓과 상호작용하여 데이터를 대기하거나 수신하거나 전송할 때만 연결 손실을 감지합니다.
• 디폴트 값: 0(비활성화)
• 적용 가능 값: 0 ~ 정수값
• 예시:
-- 클라이언트 연결 상태를 주기적으로 확인
-- 대규모 연결 환경에서 비정상 연결을 신속히 감지
client_connection_check_interval = '30s'; -- 30초마다 연결 확인
tcp_keepalives_idle
- TCP 연결 유지 신호를 보내기 전 idle(대기) 상태 유지 시간을 설정합니다.
- Windows에서는 이 값을 0으로 설정하면 2시간으로 설정됩니다.(Windows는 시스템 기본값 읽는 방법 미제공)
- 리눅스에서 기본값은 일반적으로 7200초(2시간)입니다.
• 디폴트 값: 0(운영 체제의 기본값을 사용)
• 적용 가능 값: 0 ~ 정수값(초 단위)
• 예시:
-- 클라이언트 연결이 비활성 상태인지 확인
tcp_keepalives_idle = '120'; -- 120초 동안 idle 상태일 때 TCP keepalive 시작
tcp_keepalives_interval
- 클라이언트가 확인 응답을 보내지 않은 TCP keepalive 메시지를 재전송하기까지의 시간을 지정합니다.
- Windows에서는 이 값을 0으로 설정하면 1초로 설정됩니다.(Windows는 시스템 기본값 읽는 방법 미제공)
• 디폴트 값: 0(운영 체제의 기본값을 사용)
• 적용 가능 값: 0 ~ 정수값(초 단위)
• 예시:
-- TCP 연결 유지 신호 간격 조정
tcp_keepalives_interval = '30'; -- 30초마다 TCP keepalive 신호 전송
wal_sender_timeout
- 지정된 시간 이상 비활성 상태인 복제 연결을 종료합니다.
- 이 설정은 송신 서버가 스탠바이 서버의 크래시나 네트워크 장애를 감지하는 데 유용합니다.
- 네트워크 지연이 낮은 스탠바이에 대해 더 빠른 장애 감지를 위해 작은 값을 사용하는 것이 유용합니다.
- 네트워크 지연이 높은 원격 위치에 있는 스탠바이의 상태를 더 잘 판단하기 위해 더 큰 값을 설정할 수 있습니다.
• 디폴트 값: 60000(60초)
• 적용 가능 값: 0 ~ 정수값
• 예시:
-- 스트리밍 복제 클라이언트의 연결 상태 확인
-- 복제 클라이언트가 비활성화 상태로 오래 남는 것을 방지
wal_sender_timeout = '30s'; -- 30초 동안 응답이 없으면 연결 종료
wal_receiver_timeout
- 지정된 시간 이상 비활성 상태인 복제 연결을 종료합니다.
- 이 설정은 스탠바이 서버가 기본(primary) 노드의 크래시나 네트워크 장애를 감지하는 데 유용합니다.
- 이 매개변수는 postgresql.conf 파일에서 설정하거나 서버 명령줄(command line)에서만 설정할 수 있습니다.
• 디폴트 값: 60000(60초)
• 적용 가능 값: 0 ~ 정수값
• 예시:
-- 스트리밍 복제 송신자의 연결 상태 확인
-- 복제 설정에서 데이터 전송 지연 문제를 감지
wal_receiver_timeout = '40s'; -- 40초 동안 데이터 수신이 없으면 연결 종료
이름에 timeout이 들어간 파라미터들을 다 넣자면 이거보다 더 많지만, 제가 생각하는 카테고리와는 맞지 않기 때문에 오늘은 여기까지~
카테고리 별로 하나씩 살펴볼 예정이니까 다음 포스팅도 기대해주세요!