프로그래밍/서버, DBMS

PostgreSQL lock_timeout 기준 정리

포도알77 2026. 6. 20. 12:26

본문 중간의 쿠팡 추천 상품 구매시 쿠팡 파트너스에서 일정액의 수수료를 제공받습니다.

PostgreSQL lock_timeout 기준 정리

lock_timeout은 PostgreSQL에서 쿼리 실행 시간 전체를 제한하는 옵션이 아니라, 잠금을 기다리는 시간만 제한하는 설정이다. 2026년 6월 20일 기준 PostgreSQL 공식 문서를 보면 이 값은 테이블, 인덱스, 행 등 데이터베이스 객체의 잠금 획득을 기다리는 동안에만 적용되며, 기본값 0은 제한이 없다는 뜻이다.

실무에서 이 설정이 필요한 이유는 분명하다. 배치 작업이나 DDL, 대량 수정 쿼리가 다른 세션의 잠금 때문에 오래 멈춰 있으면 애플리케이션 응답 지연이 길어질 수 있다. 반대로 값을 너무 짧게 잡으면 일시적인 경합에도 작업이 쉽게 실패한다. 선택 기준은 세 가지다. 잠금 대기가 사용자 요청 경로인지, 재시도가 쉬운 작업인지, 그리고 이미 statement_timeout을 어떻게 쓰고 있는지다.

lock_timeout은 정확히 무엇을 제한할까?

PostgreSQL 공식 문서는 lock_timeout을 "잠금을 얻기 위해 기다리는 시간이 지정한 값을 넘으면 해당 statement를 중단하는 설정"으로 설명한다. 여기서 중요한 점은 두 가지다.

  • 잠금을 기다리는 동안에만 발동한다.
  • 잠금 획득이 끝난 뒤 실제 쿼리 실행이 오래 걸리는 상황은 막지 못한다.

예를 들어 어떤 UPDATE가 다른 트랜잭션이 잡고 있는 행 잠금을 기다리느라 멈춰 있다면 lock_timeout이 의미가 있다. 하지만 잠금은 바로 잡았고 이후 정렬, 조인, 대량 스캔 때문에 실행이 오래 걸리는 경우라면 statement_timeout이 담당하는 영역이다.

statement_timeout과 무엇이 다를까?

항목 lock_timeout statement_timeout
무엇을 제한하나 잠금 대기 시간 statement 전체 처리 시간
언제 발동하나 잠금을 기다리는 동안만 서버에 쿼리가 도착한 뒤 완료될 때까지
기본값 0, 즉 비활성화 0, 즉 비활성화
공식 문서상의 주의점 statement_timeout 이상으로 잡으면 실익이 작다 전역 설정은 모든 세션에 영향을 준다

공식 문서는 statement_timeout이 0이 아닌 경우 lock_timeout을 같은 값이나 더 큰 값으로 잡는 것은 대체로 의미가 없다고 명시한다. 이유는 간단하다. statement 전체 시간 제한이 먼저 걸리기 때문이다.

따라서 두 값을 함께 쓴다면 보통 lock_timeout을 더 짧게 두고, 전체 실행 제한은 statement_timeout이 맡는 구성이 자연스럽다. 예를 들어 잠금 대기는 2초만 허용하고, 실제 실행 시간은 15초까지 허용하는 식이다.

어떤 작업에 특히 유용할까?

lock_timeout은 "기다리기보다 빨리 실패하고 다시 판단하는 편이 나은 작업"에 잘 맞는다.

  • 웹 요청 안에서 실행되는 짧은 조회나 수정
  • 스키마 변경 전 잠금 경합 여부를 빨리 확인하고 싶은 운영 작업
  • 재시도 로직이 있는 백그라운드 작업
  • SELECT ... FOR UPDATE처럼 명시적으로 잠금 획득을 시도하는 코드

반대로 긴 배치나 마이그레이션처럼 어느 정도 잠금 대기를 감수해야 하는 작업은 너무 짧은 값이 오히려 방해가 될 수 있다. 공식 문서도 이 설정이 명시적 잠금뿐 아니라 암묵적으로 획득하는 잠금에도 적용된다고 설명하므로, 애플리케이션이 직접 LOCK TABLE을 쓰지 않더라도 영향 범위는 넓다.

어디에 설정하는 것이 무난할까?

PostgreSQL 공식 문서는 lock_timeoutpostgresql.conf에서 전역 기본값으로 두는 것은 권장하지 않는다고 적고 있다. 모든 세션에 영향을 주기 때문이다. 이 문구는 실무 판단에도 직접 연결된다.

  • 애플리케이션 요청 경로마다 요구사항이 다르면 세션 또는 트랜잭션 범위에서 설정하는 편이 낫다.
  • 특정 마이그레이션 도구나 배치 계정만 다르게 가져가야 하면 그 연결 범위에 한정하는 편이 안전하다.
  • 운영팀이 전체 인스턴스 기본값으로 밀어 넣기 전에, 어떤 워크로드가 실패로 바뀌는지 먼저 확인해야 한다.

SET 문서 기준으로 SET은 현재 세션에만 적용되고, SET LOCAL은 현재 트랜잭션이 끝날 때까지만 유지된다. 그래서 일회성 운영 작업이나 특정 트랜잭션 보호에는 SET LOCAL lock_timeout = '2s' 같은 방식이 범위를 가장 좁게 잡기 쉽다.

BEGIN;
SET LOCAL lock_timeout = '2s';

UPDATE accounts
SET balance = balance - 1000
WHERE id = 10;

COMMIT;

이 예시는 문법 설명용이다. 핵심은 설정 범위를 세션 전체가 아니라 현재 트랜잭션으로 제한한다는 점이다.

값은 어느 정도부터 시작하면 될까?

공식 문서는 특정 권장 숫자를 제시하지 않는다. 따라서 값은 업무 특성으로 정해야 한다.

상황 생각해 볼 출발점 이유
사용자 요청 안의 짧은 OLTP 쿼리 수백 ms에서 1~2초 수준 응답 지연을 길게 끌기보다 실패 후 재시도나 에러 처리로 넘기는 편이 나은 경우가 많다
운영 중 DDL 실행 여부 점검 1~5초 수준 잠금 경합이 심하면 빨리 포기하고 점검 시간을 다시 잡는 편이 안전하다
백그라운드 재처리 작업 애플리케이션 요청보다 조금 길게 즉시 사용자 응답을 만들지 않지만, 무한 대기도 바람직하지 않다

여기서 중요한 것은 숫자 자체보다 상대 관계다. 잠금 대기 허용 시간은 사용자 SLA, 재시도 정책, 그리고 같은 경로의 statement_timeout보다 짧아야 해석이 쉬워진다.

 

 

자주 헷갈리는 질문

Q. lock_timeout을 걸면 느린 쿼리도 자동으로 막을까?

아니다. 공식 문서 기준으로 이 설정은 잠금 대기 중일 때만 발동한다. 실행 계획이 비효율적이어서 오래 걸리는 쿼리는 statement_timeout, 인덱스 설계, 쿼리 튜닝으로 봐야 한다.

Q. 같은 statement 안에서 잠금을 여러 번 기다리면 어떻게 될까?

공식 문서는 시간 제한이 각 잠금 획득 시도마다 별도로 적용된다고 설명한다. 따라서 하나의 statement가 여러 객체 잠금을 차례로 기다릴 수 있다면, 각 대기 구간마다 lock_timeout이 따로 평가된다.

Q. NOWAIT와는 어떤 차이가 있을까?

NOWAIT는 잠금을 전혀 기다리지 않고 즉시 실패시키는 방식이고, lock_timeout은 일정 시간까지는 기다린 뒤 실패시키는 방식이다. 즉 "기다림 자체를 없앨 것인가"와 "짧게만 허용할 것인가"의 차이다.

Q. 전역 설정으로 두면 안 될까?

기술적으로는 가능하지만 PostgreSQL 공식 문서는 postgresql.conf에서 이 값을 두는 것을 권장하지 않는다. 이유는 모든 세션이 같은 정책을 강제로 따르게 되기 때문이다. 성격이 다른 OLTP, 배치, 마이그레이션 작업이 한 인스턴스를 공유하면 부작용이 생길 수 있다.

실무 적용 순서

  1. 먼저 같은 경로의 statement_timeout 유무와 값을 확인한다.
  2. 잠금 경합이 실제 문제인 쿼리인지, 단순한 느린 실행인지 분리한다.
  3. 전역 기본값보다 세션 또는 트랜잭션 범위 설정부터 시도한다.
  4. 재시도 가능한 작업인지 확인한 뒤 짧은 값으로 시작한다.
  5. 실패 로그와 사용자 영향도를 보고 필요할 때만 늘린다.

이 순서가 유용한 이유는 분명하다. lock_timeout은 장애를 예방하는 만능 스위치가 아니라, 잠금 대기를 어디까지 허용할지에 대한 정책이기 때문이다.

정리

lock_timeout은 PostgreSQL에서 잠금 대기만 제한하는 설정이다. 쿼리 전체 실행 시간 제한은 statement_timeout이 맡고, 두 값을 함께 쓰면 보통 lock_timeout을 더 짧게 잡는 편이 해석이 쉽다.

2026년 6월 20일 기준 PostgreSQL 공식 문서를 기준으로 보면, 이 설정은 전역 기본값보다 세션이나 트랜잭션 범위에서 좁게 적용하는 편이 안전하다. 특히 사용자 요청 경로처럼 잠금 때문에 오래 멈추는 것이 더 큰 문제인 워크로드에서 유용하다.

참고 자료

반응형
페이스북으로 공유카카오톡으로 공유카카오스토리로 공유트위터로 공유URL 복사