본문 바로가기
C.W.K.
Stream
Lesson 03 of 10 · published

격리 수준

~14 min · transactions, isolation

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

동시에 실행된 작업이 무엇을 볼까

격리 수준은 한 트랜잭션이 다른 트랜잭션의 변화를 언제 볼 수 있는지 정해. PostgreSQL의 READ UNCOMMITTED는 READ COMMITTED와 똑같이 동작하므로 더티 읽기를 허용하지 않아. 기본인 READ COMMITTED에서는 반복 불가능 읽기와 팬텀 읽기가 생길 수 있지만, REPEATABLE READ는 PostgreSQL에서 둘을 막아.

더 안정된 스냅샷과 더 강한 보장

REPEATABLE READ는 트랜잭션 동안 같은 스냅샷을 유지해 반복 조회가 흔들리지 않게 해. PostgreSQL의 SERIALIZABLE은 SSI로 직렬화 이상까지 검사해 결과가 순서대로 실행한 것과 같도록 보장하고, 충돌하면 한쪽을 실패시켜. 이 실패는 버그가 아니라 재시도를 요구하는 정상 동작이야.

가장 강한 수준이 언제나 정답은 아니야

보장이 강해질수록 충돌과 재시도 비용도 커져. 실제 업무 불변식과 경쟁 모양을 보고 수준을 고르고, SERIALIZABLE을 쓴다면 전체 트랜잭션을 안전하게 재실행할 수 있게 만들어.

Code

격리 수준 명시하기·sql
BEGIN ISOLATION LEVEL REPEATABLE READ;
-- 이 트랜잭션 모든 statement 가 일관된 snapshot 봄
SELECT * FROM accounts;
-- ... 시간 지남, 다른 트랜잭션 commit ...
SELECT * FROM accounts;  -- 첫 SELECT 와 같은 view
COMMIT;
SERIALIZABLE에서 재시도 처리하기·python
def transfer_with_retry(c, from_id, to_id, amount, attempts=5):
    for i in range(attempts):
        try:
            with c.transaction(isolation_level="serializable"):
                c.execute("UPDATE accounts SET balance = balance - %s WHERE id = %s", (amount, from_id))
                c.execute("UPDATE accounts SET balance = balance + %s WHERE id = %s", (amount, to_id))
            return  # 성공
        except psycopg.errors.SerializationFailure:
            continue
    raise RuntimeError("transfer failed after %d attempts" % attempts)

External links

Exercise

psql 세션 2개를 열어. A에서 REPEATABLE READ 트랜잭션을 시작해 행을 조회하고, B에서 같은 행을 UPDATE한 뒤 COMMIT해. A에서 다시 조회하고 이어서 같은 행을 UPDATE했을 때 어떤 결과가 나는지 기록해.

Progress

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

댓글 0

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

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