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

Deadlock: 어떻게 일어나나

~12 min · transactions, deadlocks

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

두 트랜잭션, 반대 순서

Deadlock 은 트랜잭션 A 가 행 X lock 잡고 행 Y 기다리고, B 가 Y 잡고 X 기다릴 때. 둘 다 못 진행. PostgreSQL 이 cycle 감지 + 한 쪽 abort (40P01 deadlock_detected 에러).

Deadlock 레시피

UPDATE 두 개, 행 두 개, 반대 순서로 접근. 실제 시스템의 거의 모든 deadlock 이 이 패턴의 변형.

두 가지 예방

  1. 모든 코드 경로에서 같은 순서로 행 update. 항상 row 1 그 다음 row 2 건드리면, 같은 거 하는 다른 트랜잭션과 절대 deadlock 안 남.
  2. Catch and retry. 실제 워크로드에서 deadlock 이 가끔 피할 수 없음. 트랜잭션을 retry loop 로 (backoff 와) 감싸고 40P01 을 복구 가능 에러로 다룸.

Code

Deadlock 레시피 — 하지 마·sql
-- Session A                        | -- Session B
BEGIN;                              | BEGIN;
UPDATE accounts SET balance =       | UPDATE accounts SET balance =
  balance - 100 WHERE id = 1;       |   balance - 100 WHERE id = 2;
                                    |
-- A 가 B 의 2 lock 기다림           | -- B 가 A 의 1 lock 기다림
UPDATE accounts SET balance =       | UPDATE accounts SET balance =
  balance + 100 WHERE id = 2;       |   balance + 100 WHERE id = 1;
-- ERROR: deadlock detected         |
예방: 일관 순서·sql
-- 항상 낮은-id 행 먼저 lock
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = LEAST(1, 2);
UPDATE accounts SET balance = balance + 100 WHERE id = GREATEST(1, 2);
COMMIT;
Python 의 retry loop·python
import psycopg, time
for attempt in range(5):
    try:
        with conn.transaction():
            conn.execute("UPDATE accounts SET balance = balance - 100 WHERE id = %s", (from_id,))
            conn.execute("UPDATE accounts SET balance = balance + 100 WHERE id = %s", (to_id,))
        break
    except psycopg.errors.DeadlockDetected:
        time.sleep(0.05 * (2 ** attempt))  # 지수 backoff
else:
    raise RuntimeError("deadlock-retry exhausted")

External links

Exercise

Deadlock 레시피를 psql 두 세션에서 재현. deadlock_detected 에러 관찰. 그 다음 두 트랜잭션을 일관 순서로 행 lock 하도록 재작성; deadlock 더 이상 안 일어나는 거 확인.

Progress

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

댓글 0

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

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