여기서는 멈추세요
- blocker가 마이그레이션·백업·replication·핵심 트랜잭션인지 확인하지 못하면 취소하거나 종료하지 않습니다.
- 쿼리 원문에 개인정보·비밀값이 있으면 외부 티켓과 채팅에 그대로 공유하지 않습니다.
DATABASE LOCKS
SAFE OPERATING BOUNDARY
취소·종료된 현재 쿼리와 트랜잭션은 되돌릴 수 없습니다. 애플리케이션 재시도와 트랜잭션 롤백 결과를 소유자와 확인합니다.
BEFORE YOU START
CHECK THE BRANCH
다른 세션이 보유한 heavyweight lock 대기를 의미하므로 pg_blocking_pids로 직접 blocker를 찾습니다.
pg_locks만으로 해결하지 말고 wait_event의 의미와 스토리지·내부 경합을 별도 성능 범위로 분석합니다.
현재 쿼리가 idle이어도 열린 트랜잭션이 락을 유지할 수 있으므로 xact_start와 애플리케이션 연결 관리를 확인합니다.
FOLLOW THE FLOW
쿼리 원문에는 민감정보가 포함될 수 있으므로 길이를 제한하고 공유 전 가립니다.
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 대기인지 장기 실행이지만 정상인 작업인지 구분합니다.
pg_blocking_pids는 각 세션을 직접 막는 서버 PID 배열을 반환합니다.
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를 다음 단계에서 사용자·트랜잭션과 연결합니다.
종료 대상을 고르기 전에 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와 트랜잭션 영향을 확인합니다.
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과 업무 변경 시각을 대조합니다.
취소할 쿼리 또는 종료할 세션을 최소 범위로 승인받습니다.
먼저 pg_cancel_backend로 현재 쿼리만 취소하고, 세션·트랜잭션 종료가 승인된 경우에만 terminate를 사용합니다.
sudo -u postgres psql -X -d postgres -c 'SELECT pg_cancel_backend(BLOCKER_PID);'sudo -u postgres psql -X -d postgres -c 'SELECT pg_terminate_backend(BLOCKER_PID);'열린 트랜잭션은 롤백되고 클라이언트가 작업을 재시도할 수 있습니다.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와 로컬 매뉴얼을 함께 확인하세요.