요약
- Next-Key Lock은 Record Lock + Gap Lock의 조합으로, 레코드와 그 앞의 간격을 함께 잠근다
- InnoDB의 REPEATABLE READ 격리 수준에서 팬텀 리드를 방지하는 핵심 메커니즘이다
본문
잠금 종류 비교
| 잠금 타입 | 대상 | 용도 |
|---|---|---|
| Record Lock | 인덱스 레코드 자체 | 특정 행 보호 |
| Gap Lock | 레코드 사이 간격 | 새 행 삽입 방지 |
| Next-Key Lock | 레코드 + 앞 간격 | 팬텀 리드 방지 |
Record Lock
인덱스 레코드 자체에만 잠금을 건다.
-- id=10인 레코드만 잠금
SELECT * FROM users WHERE id = 10 FOR UPDATE;
Gap Lock
인덱스 레코드 사이의 간격을 잠근다. 해당 간격에 새로운 행 삽입을 방지한다.
-- 예: id가 10, 20인 레코드가 있을 때
SELECT * FROM users WHERE id = 15 FOR UPDATE;
-- id 10~20 사이 간격에 Gap Lock
-- 다른 트랜잭션이 id=12, 15, 18 등 삽입 불가
Next-Key Lock
Record Lock + Gap Lock 조합. 레코드 자체와 그 앞쪽 간격을 함께 잠근다.
인덱스: ... | 10 | 20 | 30 | ...
id=20에 Next-Key Lock 시:
- (10, 20] 범위 잠금 (10 초과 ~ 20 이하)
팬텀 리드 방지 원리
-- 트랜잭션 A
BEGIN;
SELECT * FROM orders WHERE amount > 100 FOR UPDATE;
-- amount > 100 범위에 Gap Lock 설정
-- 트랜잭션 B (대기 발생)
INSERT INTO orders (amount) VALUES (150); -- 블록됨!
-- 트랜잭션 A
SELECT * FROM orders WHERE amount > 100 FOR UPDATE;
-- 같은 결과 보장 (팬텀 리드 없음)
COMMIT;
잠금 범위 예시
인덱스에 10, 20, 30이 있을 때:
| 쿼리 | 잠금 범위 |
|---|---|
WHERE id = 20 |
(10, 20] Next-Key Lock |
WHERE id = 25 |
(20, 30) Gap Lock |
WHERE id > 15 |
(10, 20], (20, 30], (30, +∞) |
주의사항
- Gap Lock은 REPEATABLE READ 이상에서만 동작
- 유니크 인덱스로 단일 행 조회 시 Gap Lock 없이 Record Lock만 사용
- Gap Lock끼리는 충돌하지 않음 (둘 다 삽입 방지 목적)
- 범위 조회 시 예상보다 넓은 범위가 잠길 수 있음