PostgreSQL · 2026-01-20

PostgreSQL 데드락 분석과 예방 방법

PostgreSQL 데드락의 원인과 로그·쿼리 기반 분석 절차, 그리고 애플리케이션·설정 차원에서 적용 가능한 실무적 예방 방법

작성일 : 2026-01-20 ㆍ 작성자 : 관리자
post
목차

개요

데드락은 둘 이상의 트랜잭션이 서로 상대방이 보유한 자원을 기다리며 진행을 멈추는 상황이다. 빈번한 데드락은 서비스 지연과 장애로 이어진다. 본문은 데드락의 원인 이해, 로그와 쿼리로의 분석, 그리고 현실적인 예방 전략을 정리한다.

데드락의 주요 원인

데드락은 보통 다음 상황에서 발생한다.

  • 다중 트랜잭션이 서로 다른 순서로 동일 테이블의 행이나 자원을 잠금
  • 긴 트랜잭션으로 인해 잠금이 장시간 유지
  • 복합 트랜잭션 흐름에서 일관되지 않은 잠금 정책
  • 외부 시스템과의 연동으로 트랜잭션이 지연되는 경우

로그와 모니터링 설정

로그를 통해 데드락을 탐지하고 원인을 파악할 수 있다. 핵심 설정은 다음과 같다.

  • log_lock_waits = on — 잠금 대기 로그 기록
  • deadlock_timeout — 데드락 감지까지의 대기 시간 조정
  • log_min_error_statement — 에러 발생 시 SQL 같이 기록

설정 예시(간단 표기):

log_lock_waits = on
deadlock_timeout = 1s
log_min_error_statement = error

데드락 로그 예시와 해석

PostgreSQL은 데드락을 감지하면 관련 트랜잭션의 스택과 잠금 정보를 로그에 남긴다. 예시는 다음과 같다.

ERROR: deadlock detected
DETAIL: Process 12345 waits for ShareLock on transaction 67890; blocked by process 54321.
DETAIL: Process 54321 waits for ExclusiveLock on tuple (1,2) of relation "orders"; blocked by process 12345.
CONTEXT: SQL statement "UPDATE orders SET status = 'done' WHERE id = 1"

위 로그는 서로가 상대방의 잠금을 기다려 데드락이 발생했음을 보여준다. 관련 프로세스 id와 문제가 된 쿼리가 핵심 단서다.

쿼리로 현재 잠금 상태 확인

실시간 분석에는 시스템 카탈로그 조회가 유용하다. 대표적인 쿼리는 다음과 같다.

-- 잠금 보유 및 대기 정보
SELECT
  pg_stat_activity.pid,
  pg_stat_activity.query,
  pg_locks.locktype,
  pg_locks.mode,
  pg_locks.granted
FROM pg_stat_activity
JOIN pg_locks ON pg_stat_activity.pid = pg_locks.pid
WHERE pg_stat_activity.pid  pg_backend_pid();

이 쿼리는 어떤 세션이 어떤 잠금을 보유 또는 대기 중인지 보여준다. granted 컬럼으로 대기 여부 판단이 가능하다.

분석 절차

데드락 발생 시 권장되는 단계는 다음과 같다.

  • 데드락 로그 수집 후 관련 트랜잭션 쿼리와 프로세스 id 추출
  • pg_locks와 pg_stat_activity로 현재/과거 잠금 패턴 확인
  • 문제가 반복되는 쿼리나 코드 흐름 식별
  • 트랜잭션 설계와 잠금 순서 확인

예방 전략 — 애플리케이션 레벨

애플리케이션에서 수행할 수 있는 실무적 방법들이 있다.

  • 일관된 잠금 순서 유지: 여러 테이블 접근 시 항상 같은 순서로 접근
  • 트랜잭션 길이 최소화: 가능한 한 트랜잭션 내 처리량 축소
  • 낙관적 잠금 사용 고려: 업데이트 충돌이 드문 경우 버전 컬럼 활용
  • 선점 가능한 대기 처리: SELECT FOR UPDATE SKIP LOCKED 활용
-- 대기 건너뛰고 처리 가능한 행만 선택
SELECT * FROM task_queue
WHERE status = 'pending'
FOR UPDATE SKIP LOCKED;

예방 전략 — 데이터베이스 설정과 패턴

DB 측면에서 적용 가능한 방법들이다.

  • 적절한 deadlock_timeout 설정으로 빠른 감지 유도
  • statement_timeout으로 장기 실행문 제한
  • 필요 시 advisory locks로 애플리케이션 수준 동기화
  • 복잡한 업데이트는 배치로 분리해 잠금 경쟁 완화
-- 어드바이저리 락 예시
SELECT pg_try_advisory_lock(12345);
-- 처리 후
SELECT pg_advisory_unlock(12345);

추가 모니터링 팁

지속 모니터링으로 재발을 방지한다. 권장 항목은 다음과 같다.

  • 데드락 빈도와 발생 시간 추적
  • 특정 쿼리의 실행 계획과 인덱스 사용 점검
  • 장기간 잠금 보유 세션 알람 구성

결론

데드락은 원인 분석과 설계 개선으로 대부분 예방 가능하다. 로그와 시스템 뷰를 통한 정확한 진단이 우선이며, 애플리케이션의 잠금 순서 일관화와 트랜잭션 단축, 필요 시 DB 설정 조정이 실무에서 효과적이다. 꾸준한 모니터링으로 재발을 줄이는 것이 핵심이다.

postgres 데드락 해결 deadlock 분석 postgres deadlock 예방 postgres PostgreSQL 로그 분석 pg_locks SELECT FOR UPDATE SKIP LOCKED 데드락 원인 transaction 관리