REPEATABLE READ 예시

같은 범위를 다시 읽어도 결과가 흔들리지 않게, InnoDB는 읽기 종류에 따라 팬텀을 다르게 막습니다.

핵심은 하나입니다. 일관된 읽기는 새 행을 보이지 않게 유지하고, 잠금 읽기는 새 행이 들어오지 못하게 대기시킵니다.

공통 상황

T1이 age > 20 범위를 읽은 뒤 다시 같은 조건을 조회하는 동안, T2가 age = 25 행을 INSERT하려고 합니다. 팬텀 리드는 이 새 행이 재조회 결과에 끼어드는 문제입니다.

일관된 읽기 일반 SELECT
잠금 읽기 SELECT ... FOR UPDATE
무엇을 유지하나
처음 만든 ReadView를 유지

트랜잭션이 본 스냅샷을 계속 사용하므로, 나중에 생긴 행은 현재 시점의 조회 대상에서 빠집니다.

범위 자체를 잠가 최신 상태를 보호

현재 읽기는 최신 값을 다루려 하므로, 범위 안에 새 행이 생기지 못하게 막아야 같은 결과를 유지할 수 있습니다.

T2의 INSERT 처리
INSERT는 성공할 수 있음

새 행은 실제로 추가되지만, T1의 스냅샷에는 포함되지 않아서 이번 조회에서는 보이지 않습니다.

INSERT가 대기함

Gap Lock이 age > 20 범위의 빈 공간까지 잠가서, 팬텀 후보 행이 들어오는 순간 자체를 지연시킵니다.

T1이 다시 읽으면
결과 집합이 그대로 유지됨

새 행이 존재해도 T1은 계속 못 보므로, 팬텀은 가시성 제어로 사라집니다.

새 행이 아직 범위에 없음

T2가 대기 중이므로 재조회 시점에는 끼어들 행이 없고, 팬텀은 삽입 차단으로 막힙니다.

왜 중요한가
읽기 성능을 살리면서 일관성 유지

조회는 락 경쟁을 줄이고도 같은 결과를 보장할 수 있습니다.

최신 데이터를 다룰 때도 범위 일관성 유지

현재 읽기에서는 MVCC만으로 부족하므로, Next-Key Lock의 Gap Lock이 팬텀을 직접 막습니다.

정리

팬텀 방지는 한 가지 메커니즘이 아닙니다. MVCC의 스냅샷 읽기는 새 행을 안 보이게 만들고, 잠금 읽기는 새 행이 못 들어오게 만들어서 같은 범위의 결과를 안정적으로 유지합니다.