팬텀 리드
팬텀 리드는 하나의 트랜잭션 안에서 같은 조건으로 범위 조회를 반복했을 때, 다른 트랜잭션이 삽입하거나 삭제한 행 때문에 결과 집합이 달라지는 현상입니다.
발생 예시
-- 트랜잭션 A
START TRANSACTION;
SELECT * FROM orders WHERE amount > 150;
-- 트랜잭션 B
INSERT INTO orders (customer_id, amount) VALUES (4, 250);
COMMIT;
-- 트랜잭션 A
SELECT * FROM orders WHERE amount > 150;
두 번째 조회에서 처음에는 없던 행이 나타나면 팬텀 리드입니다.
원인
단일 레코드만 잠그면 기존 행의 변경은 막을 수 있지만, 조건 범위 안으로 새 행이 삽입되는 것은 막지 못할 수 있습니다. 따라서 범위 조회의 일관성을 보장하려면 레코드뿐 아니라 인덱스 사이의 공간도 제어해야 합니다.
방지 방법
- 트랜잭션 격리 수준을 높입니다.
- InnoDB에서는
SELECT ... FOR UPDATE같은 잠금 읽기에서 갭 락이나 넥스트키 락을 사용해 범위 내 삽입을 막을 수 있습니다. - MVCC 기반의 일관된 읽기에서는 스냅샷을 통해 반복 조회 결과를 유지할 수 있습니다.
핵심 정리
팬텀 리드는 같은 조건의 범위 조회 결과가 트랜잭션 중간에 달라지는 문제입니다.
범위에 새 행이 끼어드는 것을 막기 위해 InnoDB는 갭 락과 넥스트키 락을 사용합니다.