Transaction 격리 수준들을 살펴 보면, Repeatable Read 격리 수준에서 Phantom Read 문제가 발생한다.

그러나, MySQL에서 InnoDB 엔진을 사용할 경우, Repeatable Read 격리 수준에서 Phantom Read가 발생하지 않는다.
그 이유를 알아보자.
Phantom Read란 하나의 논리적인 작업 내에서 여러번 SELECT 문장 수행 시 특정 데이터가 보였다, 안보였다 하는 경우를 뜻한다.
1개만 나온다.INSERT한다.처음의 값과 count 수가 다르다.
이 현상을 Phantom Read라고 하며, Non-Reapeatable Read와 다음과 같은 차이가 있다.
None-Reapeatable Read : 특정 데이터가 바뀌어 보이는 것. ( UPADTE )
Phantom Read : 데이터의 갯수가 일치하지 않는 것. ( INSERT )
MySQL에서 Reapetable Read 격리 수준에서도 Phantom Read가 발생하지 않는 이유를 이해하기 위해 우선, InnoDB Lock을 이해해야 한다.

레코드 단위로 Lock을 걸 수 있다.우수한 동시성 덕분에 MySQL 8.0 이상 부터는 거의 표준이 되었다.Record Lock은 레코드 그 자체에 Lock을 거는 것이 아닌
Index에 Lock을 거는 방식이다.
해당 쿼리를 실행하면, t.c1=10인 행에 대해 UPDATE/INSERT/DELETE가 불가능하다.
SELECT c1 FROM THERE c1 = 10 FOR UPDATE
동일한 인덱스가 설정된 경우 해당 레코드가 모두 잠기기 때문에 Index를 설정하는 것이 매우 중요하다.
cf. 만약 Index가 설정되지 않은 Table이라면, PK를 기준으로 자동으로 생성된 클러스터 인덱스를 통해 Lock을 건다.
간격을 잠그는 것을 의미한다.해당 쿼리를 실행하면, 10 ~ 20 사이의 간격이 잠겨있기 때문에 t.c1=15인 값을 INSERT 할 수 없다.
SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE
다음과 같은 고유 인덱스를 검색하는 일에는 Gap Lock이 사용되지 않는다.
SELECT * FROM child WHERE id = 100;
Next Key Lock은 Record Lock과 Index Record 이전 간격의 Gap Lock을 조합한 잠금이다.
InnoDB에서 Phantom READ가 발생하지 않는 이유가 바로 이 Next-Key Lock 때문이다.
예를 들어. 10, 11, 13, 20의 인덱스가 있을 때 다음과 같이 Lock이 수행된다.
(negative infinity, 10]
(10, 11]
(11, 13]
(13, 20]
(20, positive infinity)
가장 큰 인덱스 값 다음의 간격에 대해서 Lock을 수행한다.
InnoDB의 Default 격리 수준이 REAPITABLE READ이고,
이 경우 Next Key Lock을 사용하기 때문에 Phantom Read가 발생하지 않는다.