명령어/DB

[PostgreSQL] SELECT FOR UPDATE / NOWAIT / FOR SHARE 행을 잠그고 안전하게 갱신한다

jykim23 2026. 7. 23. 21:58
반응형

설치·접속: PostgreSQL 설치와 접속

부제: 재고 1개를 두 요청이 동시에 빼가지 못하게, 읽는 순간 그 행을 잠그고 나만 갱신하게 하는 상황

-- 세션 A: 읽으면서 행을 잠근다. 커밋 전까지 다른 세션의 갱신을 막는다
BEGIN;
SELECT qty FROM m7_stock WHERE id=1 FOR UPDATE;   -- 이 행에 배타 락
-- ... 재고 확인 후 ...
UPDATE m7_stock SET qty = qty - 1 WHERE id=1;
COMMIT;
########## A가 FOR UPDATE로 행을 잠근 사이 B가 접근 ##########
 A: FOR UPDATE로 잠금
----------------------
                    5

--- B: NOWAIT (즉시 실패) ---
ERROR:  could not obtain lock on row in relation "m7_stock"

--- B: 그냥 FOR UPDATE (A 커밋까지 대기했다가 최신값) ---
A: 재고 차감 후 커밋
 B: 대기 후 읽은 최신 재고
---------------------------
                         4   <- A가 뺀 결과를 반영한 값

########## FOR SHARE는 여러 세션이 공유 가능, 갱신은 막음 ##########
 B: FOR SHARE 통과
-------------------
                 5   <- 공유 락끼리는 서로 통과
--- C: UPDATE 시도 (A의 공유 락 때문에 NOWAIT면 실패) ---
ERROR:  could not obtain lock on row in relation "m7_stock"

FOR UPDATE는 SELECT한 행에 배타적 행 락을 걸어, 커밋할 때까지 다른 세션이 그 행을 갱신·삭제·재잠금하지 못하게 한다. 두 번째 세션이 그냥 FOR UPDATE로 오면 A의 커밋까지 블로킹됐다가, 풀리면 A가 갱신한 최신 값(4)을 다시 읽는다. 이게 재고 차감·좌석 예약의 정석 흐름이다. 기다리고 싶지 않으면 NOWAIT로 즉시 에러를 받아 "지금 처리 중"이라고 응답하면 된다. FOR SHARE는 공유 락이라 여러 세션이 동시에 걸 수 있지만(읽는 동안 이 행이 사라지지 않음을 보장), 그 행을 실제로 갱신하려는 쪽은 막는다. 부모 행이 유지된다는 전제로 자식을 넣을 때 유용하다.

이렇게도 쓴다

기다리지 말고 잠겨 있으면 바로 에러. (조합: NOWAIT)

SELECT qty FROM m7_stock WHERE id=1 FOR UPDATE NOWAIT;

 

남이 잠근 행은 건너뛰고 안 잠긴 것만 집는다(작업 큐). (조합: SKIP LOCKED)

SELECT id FROM m7_stock WHERE qty>0 ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1;

 

갱신 안 할 거면 약한 락으로 참조 무결성만 지킨다. (조합: FOR SHARE)

SELECT id FROM m7_stock WHERE id=1 FOR SHARE;   -- 이 행 삭제/변경만 차단

 

조인에서 특정 테이블 행만 잠근다. (조합: OF 테이블명)

SELECT * FROM m7_stock s JOIN orders o ON o.pid=s.id
WHERE s.id=1 FOR UPDATE OF s;

 

락 대기 시간을 초 단위로 제한한다. (조합: lock_timeout)

SET lock_timeout = '3s';   -- 3초 안에 못 잡으면 에러
SELECT * FROM m7_stock WHERE id=1 FOR UPDATE;

 

지금 어떤 행 락 때문에 누가 막혀 있는지 본다. (조합: pg_locks)

SELECT pid, mode, granted FROM pg_locks WHERE relation='m7_stock'::regclass;
반응형