포스트

Gap Lock

Gap Lock이란

Gap Lock은 MySQL InnoDB에서 기존 레코드 자체가 아니라 인덱스 레코드 사이의 빈 구간을 잠그는 락이다.

예를 들어 인덱스 값이 10, 20, 30이라면 다음과 같은 구간을 생각할 수 있다.

  • (-∞, 10)
  • (10, 20)
  • (20, 30)
  • (30, +∞)

Gap Lock은 이 구간에 새로운 값이 끼어드는 것을 막는다.

왜 필요한가

주된 목적은 팬텀 리드를 막는 것이다. 범위 조건으로 읽은 결과가 트랜잭션 도중 달라지지 않게 하려면, 현재 존재하는 행만 잠그는 것으로는 부족할 수 있다. 중간에 새로운 행이 삽입되면 결과 집합이 바뀌기 때문이다.

Record Lock, Gap Lock, Next-Key Lock

  • Record Lock: 기존 레코드 자체 잠금
  • Gap Lock: 레코드 사이 빈 구간 잠금
  • Next-Key Lock: Record Lock + Gap Lock

InnoDB는 범위 잠금에서 보통 Next-Key Lock 전략을 사용한다.

언제 자주 보나

  • SELECT ... FOR UPDATE
  • SELECT ... LOCK IN SHARE MODE
  • 범위 조건이 있는 UPDATE, DELETE
  • REPEATABLE READ 격리 수준

인덱스가 매우 중요하다

Gap Lock은 결국 어떤 인덱스를 타고 어떤 범위를 읽는지와 연결된다. 적절한 인덱스가 없으면 예상보다 훨씬 넓은 범위를 잠그는 것처럼 보일 수 있다.

즉, 락 문제를 볼 때는 SQL만 보지 말고 실행 계획과 인덱스 구성을 같이 봐야 한다.

실무에서 헷갈리는 상황

  • 특정 행만 읽은 줄 알았는데 insert가 막힘
  • 단건 조회라 생각했는데 실제론 범위 스캔이었음
  • 격리 수준을 바꾸니 현상이 달라짐

이런 문제는 대부분 “레코드를 잠근 줄 알았는데 사실은 gap까지 잠겼다”로 해석할 수 있다.

정리

Gap Lock은 레코드를 보호하기 위한 락이 아니라, 새로운 레코드가 끼어들어 읽기 결과가 흔들리는 것을 막기 위한 락이다. InnoDB 락 문제를 해석할 때는 record만 보지 말고, range와 index까지 함께 봐야 한다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

댓글

아직 댓글이 없습니다