WEBBOOK CHAPTER

PostgreSQL 18, 입문에서 시니어까지: 30장. 동시성 장애 재현 실습

30장. 동시성 장애 재현 실습

psql session을 열고 A에서 주문 1번을 lock한 뒤 commit하지 않는다. B에서 같은 행을 update하고 C에서 blocking query를 실행한다. 대기 시간, blocker pid, query text, application_name이 런북 기록과 일치하는지 확인한다.


-- session A
begin;
select id,status from orders where id=1 for update;
select pg_sleep(60);

-- session B: 무한 대기 대신 실패 계약을 둔다.
set lock_timeout='3s';
update orders set status='CANCELED' where id=1;

다음에는 A가 1→2, B가 2→1 순서로 잠그는 deadlock을 재현한다. PostgreSQL은 한 transaction을 희생시킨다. 앱은 희생 transaction의 전체 business operation을 backoff+jitter로 재시도해야 하며, 이미 보낸 외부 API를 중복 실행하지 않게 outbox와 idempotency key를 쓴다.

수정 후 검증은 lock wait p95, deadlock count, transaction duration, affected rows를 함께 본다. FOR UPDATE SKIP LOCKED는 queue worker에 유용하지만 일반 업무 조회에 쓰면 행이 조용히 누락될 수 있다.