InnoDB의 두 번째 장치

잠금 조회는 레코드 하나가 아니라 검색 범위를 함께 잠급니다

REPEATABLE READ에서 locking read가 실행되면, InnoDB는 인덱스의 레코드와 그 주변 갭을 묶어 같은 조건에 새 행이 끼어드는 것을 막습니다.

인덱스 위에서 보는 잠금 범위
팬텀 방지는 "찾은 값"보다 "찾은 구간"을 잠그는 데서 시작됩니다
값 20을 찾는 잠금 조회라도, 실제로는 레코드 20만 묶지 않습니다. 앞쪽 갭과 다음 갭까지 잠금 단위에 포함되어 같은 조건의 재조회 결과가 흔들리지 않게 됩니다.
10
20
30
Next-Key Lock (10, 20]

레코드 20과 그 앞 빈 구간을 함께 고정합니다. 그래서 15처럼 중간에 끼어드는 INSERT가 차단됩니다.

Gap Lock (20, 30)

다음 레코드 앞의 빈 구간도 잠가, 같은 검색 범위에 25 같은 새 값이 생기지 못하게 만듭니다.

쿼리가 실제로 하는 일
조건 검색 결과를 다시 읽어도 행 수가 달라지지 않게 유지
SELECT * FROM t
WHERE val = 20
FOR UPDATE;
1
검색 기준 고정
인덱스에서 20을 찾고, 그 위치를 기준으로 잠금 범위를 계산합니다.
2
레코드 + 앞 갭 잠금
(10, 20] 가 묶여 기존 행과 그 앞쪽 삽입 지점을 함께 보호합니다.
3
다음 빈 구간도 잠금
(20, 30) 까지 잠가 같은 조건에 해당할 수 있는 새 행이 뒤늦게 생기지 못하게 합니다.
INSERT INTO t VALUES (15) 앞쪽 갭에 들어가므로 차단
INSERT INTO t VALUES (25) 다음 갭에 들어가므로 차단
핵심 takeaway: InnoDB는 값 하나를 잠그는 것이 아니라 재조회 결과를 바꿀 수 있는 인덱스 범위 전체를 잠가 팬텀 읽기를 막습니다.