canceling statement due to statement timeout은 PostgreSQL이 한 명령의 시간 예산을 넘겨 취소했다는 뜻입니다. 먼저 실제 접속의 설정값과 잠금 대기를 확인하고, 즉시 timeout을 0으로 끄거나 전체 DB 제한을 늘리지 마세요. statement_timeout에는 잠금 대기 시간도 포함될 수 있습니다. 쿼리 자체가 느린지, 다른 트랜잭션을 기다리는지, 앱·프록시에서 먼저 끊겼는지 나눠야 합니다.
이 글은 PostgreSQL 16 공식 문서를 기준으로 한 진단입니다. 다른 주 버전은 지원 설정과 동작을 해당 버전 문서에서 확인합니다. 예제는 문서 검토용 SQL이며 운영 DB에 연결하거나 쿼리를 실행한 결과는 아닙니다. 오류 메시지·시각·연결 경로를 보존한 뒤 제한된 조회부터 시작하세요.
원인 분리: 쿼리 시간·잠금 대기·트랜잭션 유휴는 다르다
| 제한/오류 | 주로 제한하는 것 | 진단 질문 |
| statement_timeout | 서버가 받은 명령의 완료까지 걸리는 시간 | 실제 실행인지 잠금 대기인지? |
| lock_timeout | 잠금을 얻기 위해 기다리는 시간 | 어느 세션이 잠금을 보유하는지? |
| idle_in_transaction_session_timeout | 열린 트랜잭션에서 다음 명령을 기다리는 유휴 시간 | 앱이 COMMIT/ROLLBACK을 놓쳤는지? |
| 앱·프록시의 timeout | 클라이언트 또는 중간 계층의 별도 예산 | DB 오류와 동일 시각에 어떤 계층이 종료했는지? |
statement_timeout은 단순히 CPU에서 SQL을 실행한 시간만 의미하지 않습니다. lock_timeout은 잠금을 기다리는 경우에만 작동하므로 statement_timeout과 같거나 더 크게 두면 후자가 먼저 걸릴 수 있습니다. idle_in_transaction_session_timeout은 진행 중인 느린 SELECT를 해결하는 설정이 아니라 열린 트랜잭션의 유휴 세션을 종료하는 설정입니다. 설정 이름이 비슷해도 같은 처방으로 쓰지 않습니다.
1. 실패하는 실제 연결에서 유효 설정을 읽는다
SHOW server_version;
SHOW statement_timeout;
SHOW lock_timeout;
SHOW idle_in_transaction_session_timeout;
SELECT current_database(), current_user;
관리자 콘솔에서 읽은 값과 앱이 실제 사용하는 연결의 값이 다를 수 있습니다. 역할·DB별 설정, 연결 문자열 옵션, 연결 뒤 SET, 풀의 재사용 세션 상태를 함께 확인합니다. 값에 단위가 없을 때 밀리초로 해석되는 설정이 있으므로 변경 시에는 s·ms 등 단위를 명시합니다. 연결 계정 이름과 DB 이름을 확인하는 결과를 공개 로그에 무조건 복사하지 않습니다.
연결 풀 앞에서 읽는다면 동일 요청이 어느 DB·역할로 연결됐는지 확인하고, 재사용되는 세션에 어떤 설정이 남는지도 봅니다. 새 연결 하나에서 정상인 것과 모든 풀 연결에서 정상인 것은 다릅니다. 오류가 난 트랜잭션은 먼저 실패 상태를 처리해야 하므로, 이미 중단된 트랜잭션에서 진단 SQL을 계속 붙이는 대신 앱의 ROLLBACK과 별도의 안전한 관찰 연결을 사용합니다.
2. 잠금 대기와 오래 열린 트랜잭션을 관찰한다
SELECT pid, state, wait_event_type, wait_event,
now() - xact_start AS transaction_age,
now() - query_start AS query_age,
pg_blocking_pids(pid) AS blocking_pids
FROM pg_stat_activity
WHERE datname = current_database()
AND pid <> pg_backend_pid()
ORDER BY xact_start NULLS LAST;
이 조회는 세션을 취소하거나 종료하지 않습니다. 권한에 따라 다른 세션의 일부 정보가 보이지 않을 수 있으며, 표시되지 않는 값을 정상이나 0으로 해석하지 않습니다. active 상태에서 Lock 대기라면 blocking_pids가 가리키는 세션의 업무와 트랜잭션 경계를 확인합니다. idle in transaction이라면 query_age만으로 현재 SQL이 계속 실행 중이라고 판단하지 않습니다. 오래 열린 트랜잭션의 시작 시각과 앱의 요청 경로를 함께 봅니다.
반대로 잠금 대기가 아니라면 데이터 범위·인덱스·실행 계획·스토리지·동시 실행량을 검토합니다. 관측값 하나만으로 인덱스 부재나 CPU 부족을 확정하지 않습니다. EXPLAIN ANALYZE는 쿼리를 실제 실행하므로, 변경 쿼리나 비싼 조회를 운영에서 무심코 실행하지 않습니다. 먼저 안전한 환경과 부하·권한을 정하고 필요한 실행 계획만 수집합니다.
3. 일괄 변경 대신 한 작업의 시간 예산을 제한한다
업무상 더 긴 시간이 필요한 작업은 그 연결 또는 트랜잭션 범위에서 제한을 설정하는 방식을 검토합니다. 아래는 읽기 전용 트랜잭션 안에서 설정 범위를 확인하는 예시입니다. 5초와 1초는 설명용 값이며 권장 운영값이나 성능 측정값이 아닙니다. 실제 조회를 추가하기 전에 예상 부하와 호출 계층의 제한을 조정해야 합니다.
BEGIN READ ONLY;
SET LOCAL statement_timeout = '5s';
SET LOCAL lock_timeout = '1s';
SHOW statement_timeout;
SHOW lock_timeout;
-- 필요한 읽기 쿼리는 안전한 환경에서 별도 검증
ROLLBACK;
SET LOCAL은 현재 트랜잭션에 적용되며 종료 후 이전 값으로 돌아갑니다. 오류가 발생하면 열린 트랜잭션을 ROLLBACK하고 연결을 정상 상태로 반환하는 처리도 필요합니다. 연결 풀에서 세션 SET을 쓰는 경우에는 다음 사용자에게 설정이 남지 않도록 실제 풀 동작과 복원을 확인합니다. 전역 설정을 먼저 늘리면 상관없는 짧은 요청의 보호 장치까지 바뀔 수 있습니다.
확인 방법과 반복 재시도 주의사항
교정 뒤 같은 조건의 요청에서 유효 timeout, 잠금 대기 유무, 소요 시간, 서버 오류와 앱 오류의 시각을 다시 확인합니다. DB의 취소 오류가 없어졌어도 프록시가 먼저 끊기면 사용자는 실패를 겪습니다. 전체 요청 예산에는 풀 대기와 네트워크 왕복도 있으므로 DB 제한 하나만 늘려 성공을 확정하지 않습니다.
statement timeout은 실패한 작업의 재실행을 무조건 정당화하지 않습니다. 외부 결제·메시지·다른 트랜잭션의 부작용은 DB 취소와 함께 되돌아간다고 보장할 수 없습니다. 읽기와 쓰기를 구분하고, 멱등성·완료 확인·최대 시도 수·백오프를 정합니다. 잠금 보유 세션을 강제 종료하거나 취소하는 조치는 담당자와 영향 확인 뒤 별도 변경으로 수행합니다. 이 글의 SQL에는 그런 강제 조치가 없습니다.
FAQ
statement_timeout을 0으로 바꾸면 해결인가요? 제한을 비활성화할 뿐 느린 실행이나 잠금 보유 원인을 해결하지 않습니다. 특정 작업의 예산과 진단 결과로 판단합니다.
lock_timeout을 더 크게 하면 되나요? statement_timeout이 더 먼저 도달하면 의미가 없을 수 있습니다. 잠금 대기 원인과 두 제한의 순서를 먼저 확인합니다.
idle in transaction과 느린 쿼리는 같은가요? 아닙니다. 전자는 열린 트랜잭션이 다음 명령을 기다리는 상태입니다. 앱의 트랜잭션 종료와 풀 반환 처리를 확인합니다.
공식 출처와 관련 글
공식 자료 확인일은 2026년 10월 14일입니다. 아래 예시는 문서로 검토한 설정·진단 절차이며 운영 계정이나 서버에서 직접 실행한 결과가 아닙니다. 발행일의 가격이나 실제 성능을 확정하지 않습니다.
PostgreSQL 16: statement_timeout·lock_timeout·idle 시간 제한
PostgreSQL 16: pg_stat_activity 상태와 대기
PostgreSQL 16: pg_blocking_pids 등 세션 정보 함수
PostgreSQL 16: SET LOCAL의 트랜잭션 적용 범위
함께 확인하면 좋은 글: PostgreSQL deadlock detected와 트랜잭션 재시도

'소프트웨어개발' 카테고리의 다른 글
| Nginx 정적 파일 404 해결: root·alias 경로와 try_files 점검 순서 (0) | 2026.10.15 |
|---|---|
| NAT Gateway와 VPC 엔드포인트 비교: 비공개 ECR 이미지 다운로드 비용·경로 선택 (0) | 2026.10.15 |
| Secrets Manager와 Parameter Store 비교: DB 비밀번호 회전·설정값·조회 비용 선택 (0) | 2026.10.15 |