데이터베이스 격리 수준에서 Phantom Read는 무엇이며 어떻게 방지할 수 있나요?
답변 포인트
같은 조건으로 다시 조회했을 때 새 행이 나타나는 상황을 떠올려보세요.
정답 및 해설
빠른 요약
Phantom Read는 하나의 트랜잭션 안에서 같은 조건으로 범위 조회를 두 번 했는데, 중간에 다른 트랜잭션이 조건에 맞는 행을 삽입하거나 삭제해 결과 행의 집합이 달라지는 현상입니다. 예를 들어 A 트랜잭션이 `price >= 10000`인 상품을 조회했습니다.
Phantom Read는 하나의 트랜잭션 안에서 같은 조건으로 범위 조회를 두 번 했는데, 중간에 다른 트랜잭션이 조건에 맞는 행을 삽입하거나 삭제해 결과 행의 집합이 달라지는 현상입니다.
예를 들어 A 트랜잭션이 price >= 10000인 상품을 조회했습니다. 그 사이 B 트랜잭션이 조건에 맞는 상품을 추가하고 커밋하면, A가 같은 쿼리를 다시 실행했을 때 처음에는 없던 행이 “유령처럼” 나타납니다.
Dirty Read는 커밋되지 않은 값을 읽는 문제이고, Non-repeatable Read는 같은 행의 값이 바뀌는 문제입니다. Phantom Read는 값 하나보다 “조건에 맞는 행의 집합”이 변하는 문제라는 점이 다릅니다.
방지 방법은 DB 엔진과 격리 수준에 따라 다릅니다. 일반적으로 Serializable 수준은 범위 잠금이나 predicate lock을 통해 Phantom Read를 막습니다. MySQL InnoDB의 Repeatable Read는 MVCC와 next-key lock을 조합해 많은 경우 phantom을 방지합니다.
하지만 격리 수준을 높이면 동시성이 떨어지고 lock 대기가 늘 수 있습니다. 따라서 결제, 재고, 정산처럼 정확성이 중요한 구간에 선택적으로 적용하는 것이 실무적입니다.