한양과학기술고등학교

에듀테크 프로젝트 대시보드

잠금 (Lock)

FOR UPDATE SKIP LOCKED deadlock advisory lock pg_locks

쓰기 충돌을 막는 장치. 대부분 자동으로 잡히지만, 큐·재고 차감 같은 패턴은 명시적으로 다룹니다.

1. 행 잠금

BEGIN;
  SELECT * FROM seats WHERE id = 5 FOR UPDATE;   -- 이 행을 잠금 (다른 FOR UPDATE 는 대기)
  UPDATE seats SET taken = true WHERE id = 5;
COMMIT;
구문용도
FOR UPDATE곧 수정/삭제할 행 선점
FOR NO KEY UPDATEPK 안 바꾸는 수정 (FK 참조와 덜 충돌)
FOR SHARE읽는 동안 남이 못 바꾸게 (약한 잠금)
... NOWAIT / ... SKIP LOCKED대기 대신 에러 / 잠긴 행 건너뛰기

2. 작업 큐 패턴

-- 워커 여러 개가 서로 안 겹치게 하나씩 집어감
UPDATE jobs SET status = 'running', picked_at = now()
WHERE id = (
    SELECT id FROM jobs WHERE status = 'queued'
    ORDER BY id
    FOR UPDATE SKIP LOCKED
    LIMIT 1
)
RETURNING *;

3. 데드락

T1: UPDATE a ...   (a 잠금)        T2: UPDATE b ...   (b 잠금)
T1: UPDATE b ...   (b 대기)   ×    T2: UPDATE a ...   (a 대기)  → 교착
예방
  • 여러 행을 갱신할 때 항상 같은 순서(예: id 오름차순)로 잠그기
  • PG 가 deadlock_timeout(1초) 후 감지해 한쪽을 40P01 로 중단 → 재시도

4. Advisory lock · 관찰

-- 애플리케이션 레벨 뮤텍스 (테이블과 무관한 임의 키)
SELECT pg_try_advisory_lock(12345);   -- true 면 획득
-- ... 크리티컬 섹션 ...
SELECT pg_advisory_unlock(12345);

-- 지금 걸린 잠금과 대기 관계
SELECT pid, locktype, mode, granted FROM pg_locks WHERE NOT granted;
SELECT pg_blocking_pids(pid), * FROM pg_stat_activity WHERE wait_event_type = 'Lock';
"VACUUM 은 선택이 아니라 MVCC 가 물리는 세금이다"