[ MySQL ] Phantom READ

Manx·2023년 9월 25일
0

DBMS

목록 보기
6/8

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

그러나, MySQL에서 InnoDB 엔진을 사용할 경우, Repeatable Read 격리 수준에서 Phantom Read가 발생하지 않는다.

그 이유를 알아보자.


1. Phantom Read

Phantom Read란 하나의 논리적인 작업 내에서 여러번 SELECT 문장 수행 시 특정 데이터가 보였다, 안보였다 하는 경우를 뜻한다.

  1. Transaction A에서 처음 SELECT를 수행했을 때 age가 15보다 큰 레코드는 없기 때문에, 결과가 1개만 나온다.
  2. Transaction A의 작업이 끝나지 않은 상태로 Transaction B가 age가 22인 레코드를 INSERT한다.
  3. Transaction A가 다시 SELECT 했을 때, 처음의 값과 count 수가 다르다.

이 현상을 Phantom Read라고 하며, Non-Reapeatable Read와 다음과 같은 차이가 있다.

None-Reapeatable Read : 특정 데이터가 바뀌어 보이는 것. ( UPADTE )
Phantom Read : 데이터의 갯수가 일치하지 않는 것. ( INSERT )


2. InnoDB Lock

MySQL에서 Reapetable Read 격리 수준에서도 Phantom Read가 발생하지 않는 이유를 이해하기 위해 우선, InnoDB Lock을 이해해야 한다.


1. Record Lock

  • InnoDB는 다른 스토리지 엔진과 다르게 레코드 단위로 Lock을 걸 수 있다.
  • 레코드 단위로 Lock을 잡을 수 있는 우수한 동시성 덕분에 MySQL 8.0 이상 부터는 거의 표준이 되었다.
  • MySQL 엔진이 아닌, 스토리지 엔진에서 Lock을 잡기 때문에, MySQL 명령어로 해당 Lock을 관찰하는 것은 어렵다.

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을 건다.


2. Gap Lock

  • Gap 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;

3. Next-Key Lock

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가 발생하지 않는다.


참조

profile
백엔드 개발자

0개의 댓글