핵심 요약
대부분의 웹 워크로드는 기본값 Read Committed로 충분하다. 하지만 "읽고-검사하고-쓰는"(재고 차감, 잔액 이체) 패턴은 동시성에서 어긋나므로 SELECT ... FOR UPDATE 잠금이나 더 강한 격리(Repeatable Read/Serializable)가 필요하다. 데드락은 "잠금 순서를 일정하게" 유지하면 크게 준다.
1. 격리수준
| 수준 | 막는 현상 |
|---|---|
| Read Committed | dirty read |
| Repeatable Read | + non-repeatable read |
| Serializable | + phantom(직렬화 보장) |
2. 안전한 차감
BEGIN;
SELECT stock FROM items WHERE id=$1 FOR UPDATE; -- 행 잠금
UPDATE items SET stock = stock - 1 WHERE id=$1;
COMMIT;
3. 함정
- 여러 행을 잠글 때 트랜잭션마다 잠금 순서가 다르면 데드락 — 항상 같은 순서(예: id 오름차순)로 잠가라
- Serializable은 충돌 시 직렬화 실패로 롤백 — 재시도 로직 필요
- 트랜잭션을 길게 열어두면 잠금 경합·부풀음 유발
자주 묻는 질문
재고 차감이 가끔 음수가 됩니다.
읽기와 쓰기 사이에 다른 트랜잭션이 끼어든 경쟁 조건입니다. FOR UPDATE로 행을 잠그거나 UPDATE ... WHERE stock > 0 원자적 갱신으로 해결하세요.
데드락을 완전히 없앨 수 있나요?
완전 제거는 어렵지만 잠금 순서를 일정하게 하고 트랜잭션을 짧게 유지하면 크게 줍니다. 남는 데드락은 감지 후 재시도로 처리합니다.

댓글 0