[1.23]Gap,Next Key Lock을 활용한 Phantom Read 방지

Always·2025년 1월 23일
1

매일메일

목록 보기
25/69

https://www.maeil-mail.kr/question/93
요약: 갭 락과 넥스트 키 락을 사용해서 Phantom Read를 방지 할 수 있다.

Phantom read

다음과 같은 상황을 살펴보자

트랜잭션 a: select * from table where id>1;,select * from table where id>1;,
트랜잭션 b  Insert into table  (a,b,c) values(a,b,c)

트랜잭션 a는 두번의 읽기 과정을 수행하고 b는 a에서 읽어들여지는 데이터를 수정한다. 이 때 만약 a의 두번의 읽기 사이에 b의 update쿼리가 수행된다면 a에서 읽어들여지는 두번의 select문의 결과가 다르게 될 것이다.

이렇게 같은 트랜잭션내에서 같은 읽기의 작업을 수행했는데, 다른 값이 나오는 것을 Phantom Read라고 한다.

Gap Lock과 Next Key Lock


출처: https://gisungcu.tistory.com/645
인덱스와 인덱스 사이에 있는 빈공간을 락을 걸어서 위의 사례처럼 발생이 안되게 할 수 있다.
이를 Gap Lock이라고 한다.
Gap Lock을 이용하면, 특정 select 문을 사용하고 있을 때 빈 공간 즉 Gap에 락을 걸어서,
다른 트랜잭션에서 접근하여 삽입하는 요청을 기다리게한다. 기다린 write 요청은 락이 해제되면 그 후에 수행하여, phantom read를 막을 수 있다.

Next Key Lock은 특정 레코드와 위의 gap에 락을 거는 범위를 지정해서 락을 거는 것이다.

아래의 코드를 통해서 잠금이 가능하다.

- 트랜잭션 1 (Session 1)
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;

-- age가 25 이상 35 이하인 데이터를 조회하면서 FOR UPDATE로 잠금
SELECT * FROM users WHERE age BETWEEN 25 AND 35 FOR UPDATE;
-- 트랜잭션 2 (Session 2)
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;

-- 새로운 레코드 삽입 시도
INSERT INTO users (name, age) VALUES ('David', 28);

이 때 트랜잭션 2는 1이 끝날 때까지 기다린 후에 실행되어서 phantom read를 막을 수 있다.

profile
🐶개발 블로그

0개의 댓글