C.W.K.
Stream
Lesson 09 of 10 · published

앱 코드의 Race Condition

~12 min · transactions, concurrency

Level 0스키마 새싹
0 XP0/86 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

고전적 race

"재고 read; > 0 면 감소 + 판매 확인." 두 요청이 병렬 실행. 둘 다 재고 = 1 read. 둘 다 안전하다 결정. 둘 다 감소. 재고 이제 -1, 없는 거 팔았음. 버그가 어떤 단일 line 에 없음 — read 와 write 사이 갭에 있음.

때에 따라 적절한 세 수정

  1. Atomic UPDATE — check 와 감소를 한 statement 에: UPDATE products SET inventory = inventory - 1 WHERE id = ? AND inventory > 0. 0 행 update 됐으면 판매 실패.
  2. SELECT FOR UPDATE — read 시 행 lock; 앱 코드에서 조건 로직; UPDATE; COMMIT.
  3. SERIALIZABLE isolation — PostgreSQL 이 충돌 감지 + retry 요청.

가장 흔한 거

Atomic UPDATE 가 보통 가장 깨끗한 답. 라운드트립 한 번, 명시 lock 없음, retry 없음. 조건 로직이 단일 SQL statement 에 fit 하기 너무 복잡할 때 SELECT FOR UPDATE.

Code

Atomic UPDATE — 재고 패턴·sql
UPDATE products
SET inventory = inventory - 1
WHERE id = :product_id AND inventory > 0
RETURNING inventory;
-- RETURNING 이 행 반환: 판매 성공.
-- 행 반환 없음: 매진, UPDATE 가 아무것도 매치 안 함.
SELECT FOR UPDATE — 로직 복잡할 때·sql
BEGIN;
SELECT inventory, max_per_customer, customer_purchase_count(?, ?)
FROM   products
WHERE  id = ?
FOR UPDATE;
-- ... 앱에서 복잡한 비즈니스 로직 ...
UPDATE products SET inventory = inventory - 1 WHERE id = ?;
COMMIT;
SERIALIZABLE — Postgres 가 referee·python
def safe_purchase(c, product_id, customer_id):
    for attempt in range(5):
        try:
            with c.transaction(isolation_level="serializable"):
                inv = c.execute("SELECT inventory FROM products WHERE id = %s", (product_id,)).fetchone()[0]
                if inv > 0:
                    c.execute("UPDATE products SET inventory = inventory - 1 WHERE id = %s", (product_id,))
            return True
        except psycopg.errors.SerializationFailure:
            continue
    return False

External links

Exercise

코드에서 race 가능한 'read 후 write' 패턴 찾기. WHERE 절에 check 있는 atomic UPDATE 로 재작성. 동시 클라이언트 두 개로 실행해서 확인.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.