격리 수준은 ‘무엇을 허용하는가’의 목록이다

격리 수준을 외울 때 흔히 표를 통째로 암기한다. 하지만 이 표는 어떤 이상 현상을 허용할지를 정한 계약서에 가깝다. 낮출수록 동시성이 올라가고 이상 현상을 더 많이 감수한다.

Read Committed

커밋되지 않은 데이터는 읽지 않는다. 여기까지는 직관적이다.

문제는 같은 트랜잭션 안에서 같은 쿼리를 두 번 실행하면 결과가 다를 수 있다는 것이다. 그 사이 다른 트랜잭션이 값을 바꾸고 커밋했다면 두 번째 조회에 반영된다. 이걸 non-repeatable read라고 부른다.

잔액을 읽고 계산한 뒤 다시 읽어 검증하는 코드는 이 수준에서 깨진다.

Repeatable Read

트랜잭션이 시작한 시점의 스냅샷을 계속 본다. 다른 트랜잭션이 무엇을 커밋하든 내가 보는 값은 변하지 않는다.

MySQL InnoDB와 PostgreSQL 모두 MVCC로 구현한다. 값을 덮어쓰는 대신 버전을 남기고, 각 트랜잭션은 자기 시점에 맞는 버전을 읽는다. 그래서 읽기가 쓰기를 막지 않는다.

팬텀 리드

범위 조회에 새로 삽입된 행이 끼어드는 현상이다. 표준적으로는 Repeatable Read에서도 허용되지만, InnoDB는 갭 락으로 조회한 범위 자체를 잠가 상당 부분 막는다. 같은 이름의 격리 수준이 DB마다 다르게 동작한다는 뜻이다.

실무에서 확인할 것

정리

격리 수준은 성능 손잡이가 아니라 정확성 계약이다. 올리기 전에 “지금 무엇이 깨지고 있는가”를 먼저 특정해야 한다.