북스터디/Real MySQL 8.0
[Real MySQL 8.0] MySQL 엔진의 잠금 - InnoDB 엔진 편
연유뿌린빙수
2025. 5. 15. 12:45
InnoDB 스토리지 엔진의 잠금

MySQL의 InnoDB 스토리지 엔진은 트랜잭션의 무결성과 동시성을 보장하기 위해 여러 가지 잠금(lock) 방식을 제공한다. 단순히 "레코드만" 잠그는 게 아니라, 인덱스를 기반으로 잠금이 걸린다는 점이 핵심이다.
이 차이가 굉장히 중요한 의미를 가지므로 정리해본다.
- 레코드 락
- 이름 그대로 레코드 자체만을 잠그는 것. Record Only Lock ( 다른 상용 DBMS의 레코드 락과 동일한 역할이다.)
- 한가지 중요한 차이는, InnoDB 스토리지 엔진은 InnoDB에서는 레코드 자체가 아닌 인덱스 레코드에 대해 잠금을 건다.
- 인덱스가 없는 테이블이라도 자동으로 생성되는 클러스터 인덱스를 이용해 잠금이 걸린다.
- 변경 시 어떤 인덱스를 이용하느냐에 따라 락 방식이 달라진다.
- 프라이머리 키 / 유니크 인덱스 기반 변경 → 해당 레코드만 잠금
- 보조 인덱스 기반 변경 → 넥스트 키 락(Next Key Lock) 또는 갭 락(Gap Lock) 사용
- 갭 락 ( Gap Lock )
- 레코드 자체가 아니라 레코드와 레코드 사이의 간격(gap)을 잠근다.
- 새로운 레코드가 그 간격에 INSERT 되는 것을 막기 위해 사용된다.
- 단독으로 사용되기보다는, 보통 넥스트 키 락의 일부로 사용된다.
- 넥스트 키 락 ( Next Key Lock )
- 넥스트 키 락 (Next Key Lock) = 레코드 락 + 갭 락
- 특정 레코드를 잠그면서 동시에 그 앞뒤 간격까지 잠근다.
- MySQL에서 STATEMENT 포맷 바이너리 로그 + Repeatable Read 격리 수준을 사용할 경우 활성화된다.
- 목적: 레플리카 서버에서 실행될 때도 동일한 결과를 보장하기 위함이다.
- 하지만 이로 인해 데드락이나 불필요한 대기가 자주 발생한다.
- 해결책: 가능하다면 바이너리 로그 포맷을 ROW 형태로 바꿔서 넥스트 키 락과 갭 락 사용을 줄이는 것이 좋다.
- 자동증가 락 (AUTO_INCREMENT Lock)
-
- AUTO_INCREMENT 속성을 가진 컬럼에서 새로운 레코드 저장 시 사용된다.
- 동시에 여러 INSERT가 실행되더라도 중복되지 않고 순서대로 증가하는 값을 보장해야 하기 때문이다.
- 특징:
- 테이블에 단 하나만 존재한다.
- 한 트랜잭션이 AUTO_INCREMENT 락을 걸면 다른 INSERT는 기다려야 한다.
- UPDATE, DELETE에서는 필요 없다.
- 제어 방법: innodb_autoinc_lock_mode 변수
- 0 : 모든 INSERT 문장에서 자동 증가 락 사용
- 1 : MySQL이 INSERT 건수를 예측할 수 있으면 가벼운 뮤텍스로 대체 (일반적으로 추천)
- 2 : 항상 뮤텍스 사용. 대신 연속된 증가값 보장은 안 된다.
- 참고: AUTO_INCREMENT 값은 한 번 증가하면 절대 줄어들지 않는다. 실패한 INSERT도 값은 소모된다.
-
정리해보자면
보조 인덱스를 이용한 변경 작업 -> 넥스트 키 락(Next Key lock), Gap lock
프라이머리 키 또는 유니크 인덱스에 의한 변경 -> 레코드 자체에 대한 락을 이용
인덱스와 잠금
- InnoDB의 모든 잠금은 레코드가 아니라 인덱스를 잠그는 방식으로 동작한다.
- 즉, 변경할 레코드를 찾기 위해 검색된 인덱스 레코드 전체에 잠금이 걸린다.
- 이 때문에 인덱스 설계는 단순 조회 성능뿐 아니라 동시성 제어와 잠금 경합에도 큰 영향을 준다.