Haru Utils

DATABASE LOCKS

PostgreSQL 장기 쿼리와 락 대기가 발생할 때

대기 세션과 blocking PID를 연결하고 락 종류·트랜잭션 나이·소유 작업을 확인한 뒤 취소와 종료를 단계적으로 판단합니다.
PostgreSQL lock waitpg_blocking_pidspg_lockslong running queryidle in transaction
환경PostgreSQL 14·15·16·17·18 · 관리자용 모니터링 권한
분류데이터베이스
검토일2026-08-27
진행5단계 · 조회 우선

SAFE OPERATING BOUNDARY

중단·복구 기준부터 확인하세요

STOP CONDITIONS

여기서는 멈추세요

  • blocker가 마이그레이션·백업·replication·핵심 트랜잭션인지 확인하지 못하면 취소하거나 종료하지 않습니다.
  • 쿼리 원문에 개인정보·비밀값이 있으면 외부 티켓과 채팅에 그대로 공유하지 않습니다.
ROLLBACK

복구 기준

취소·종료된 현재 쿼리와 트랜잭션은 되돌릴 수 없습니다. 애플리케이션 재시도와 트랜잭션 롤백 결과를 소유자와 확인합니다.

ESCALATION PACK

담당자에게 전달할 자료

  • blocked·blocker PID, 사용자, application_name과 xact_age
  • wait_event_type·wait_event와 미승인 pg_locks 목록
  • 취소·종료 승인자, 조치 시각과 락 해소 후 애플리케이션 결과
공식 문서와 읽기 전용 진단 명령을 우선 검토했습니다. 실제 서버에서는 설치된 버전의 --help와 man을 함께 확인하세요.

BEFORE YOU START

이런 증상에서 시작합니다

  • 쿼리가 끝나지 않고 wait_event_type Lock
  • DDL·배치 후 다른 요청 정체
  • idle in transaction 세션이 락 유지
  • DB CPU는 낮지만 응답 지연

CHECK THE BRANCH

놓치기 쉬운 원인 분기

01

wait_event_type이 Lock

다른 세션이 보유한 heavyweight lock 대기를 의미하므로 pg_blocking_pids로 직접 blocker를 찾습니다.

02

Lock이 아닌 I/O·LWLock 대기

pg_locks만으로 해결하지 말고 wait_event의 의미와 스토리지·내부 경합을 별도 성능 범위로 분석합니다.

03

idle in transaction이 blocker

현재 쿼리가 idle이어도 열린 트랜잭션이 락을 유지할 수 있으므로 xact_start와 애플리케이션 연결 관리를 확인합니다.

FOLLOW THE FLOW

순서대로 확인하기

1
조회시스템을 변경하지 않는 확인 단계

현재 활동과 대기 이벤트 확인

쿼리 원문에는 민감정보가 포함될 수 있으므로 길이를 제한하고 공유 전 가립니다.

활성·대기 세션
sudo -u postgres psql -X -d postgres -c "SELECT pid, usename, application_name, state, wait_event_type, wait_event, now() - query_start AS query_age, left(query, 120) AS query FROM pg_stat_activity WHERE state <> 'idle' ORDER BY query_start NULLS LAST;"
결과 읽기

query_age가 길다는 사실만으로 문제로 단정하지 않고 wait_event_type과 업무 목적을 함께 확인합니다.

다음 판단

Lock 대기인지 장기 실행이지만 정상인 작업인지 구분합니다.

2
조회시스템을 변경하지 않는 확인 단계

blocked PID와 blocking PID 연결

pg_blocking_pids는 각 세션을 직접 막는 서버 PID 배열을 반환합니다.

대기 세션별 blocker
sudo -u postgres psql -X -d postgres -c "SELECT pid AS blocked_pid, pg_blocking_pids(pid) AS blocking_pids, wait_event, now() - query_start AS wait_age FROM pg_stat_activity WHERE cardinality(pg_blocking_pids(pid)) > 0 ORDER BY query_start;"
결과 읽기

blocking_pids가 비어 있지 않은 세션만 직접 락 대기 중입니다.

다음 판단

blocked와 blocker PID를 다음 단계에서 사용자·트랜잭션과 연결합니다.

3
주의서버 부하나 권한을 고려할 단계

blocker 소유자와 트랜잭션 나이 확인

종료 대상을 고르기 전에 blocker의 사용자, 애플리케이션, 상태와 트랜잭션 시작 시각을 확인합니다.

blocker 상세
sudo -u postgres psql -X -d postgres -c "SELECT blocked.pid AS blocked_pid, blocker.pid AS blocker_pid, blocker.usename, blocker.application_name, blocker.state, now() - blocker.xact_start AS blocker_xact_age, left(blocker.query, 120) AS blocker_query FROM pg_stat_activity AS blocked CROSS JOIN LATERAL unnest(pg_blocking_pids(blocked.pid)) AS x(blocker_pid) JOIN pg_stat_activity AS blocker ON blocker.pid = x.blocker_pid ORDER BY blocker.xact_start NULLS LAST;"
결과 읽기

오래된 idle in transaction, 예상하지 못한 DDL 또는 배치가 blocker인지 확인합니다.

다음 판단

애플리케이션·DB 담당자에게 PID와 트랜잭션 영향을 확인합니다.

4
조회시스템을 변경하지 않는 확인 단계

미승인 락 종류와 영향 범위 확인

granted=false인 락과 대상 relation을 확인하되 행 수준 락은 relation 정보만으로 전부 식별되지 않을 수 있습니다.

대기 중인 락
sudo -u postgres psql -X -d postgres -c "SELECT pid, locktype, mode, granted, relation::regclass AS relation, transactionid FROM pg_locks WHERE NOT granted ORDER BY pid;"
현재 대기 유형
sudo -u postgres psql -X -d postgres -c "SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event IS NOT NULL ORDER BY pid;"
결과 읽기

Lock 외 대기는 blocker 종료로 해결되지 않을 수 있습니다. relation과 업무 변경 시각을 대조합니다.

다음 판단

취소할 쿼리 또는 종료할 세션을 최소 범위로 승인받습니다.

5
변경데이터·서비스 상태가 달라질 수 있는 단계

쿼리 취소부터 적용하고 락 해소 재검증

먼저 pg_cancel_backend로 현재 쿼리만 취소하고, 세션·트랜잭션 종료가 승인된 경우에만 terminate를 사용합니다.

변경 단계입니다. 실행 전 대상 이름과 경로, 서비스 중단 영향, 복구 방법을 다시 확인하세요.
blocker 쿼리 취소
sudo -u postgres psql -X -d postgres -c 'SELECT pg_cancel_backend(BLOCKER_PID);'
승인된 blocker 세션 종료
sudo -u postgres psql -X -d postgres -c 'SELECT pg_terminate_backend(BLOCKER_PID);'
열린 트랜잭션은 롤백되고 클라이언트가 작업을 재시도할 수 있습니다.
잔여 blocker 확인
sudo -u postgres psql -X -d postgres -c "SELECT pid, pg_blocking_pids(pid) FROM pg_stat_activity WHERE cardinality(pg_blocking_pids(pid)) > 0;"
결과 읽기

대기 세션이 진행되고 blocking_pids 결과가 비어 있으며 애플리케이션 오류율이 정상화되어야 합니다.

다음 판단

재발하면 트랜잭션 범위, DDL 실행 절차와 lock_timeout·statement_timeout 정책을 검토합니다.

PRIMARY REFERENCES

공식 문서

배포판과 버전에 따라 옵션·로그 위치가 다를 수 있습니다. 실행 전 서버의 --help와 로컬 매뉴얼을 함께 확인하세요.

도구 빠른 검색

최근 사용한 도구를 다시 열거나, 이름과 기능으로 검색하세요.

검색어와 도구의 입력·결과는 저장하지 않습니다.

↑↓ 이동 · Enter 열기 · Esc 닫기