북스터디/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의 모든 잠금은 레코드가 아니라 인덱스를 잠그는 방식으로 동작한다.
  • 즉, 변경할 레코드를 찾기 위해 검색된 인덱스 레코드 전체에 잠금이 걸린다.
  • 이 때문에 인덱스 설계는 단순 조회 성능뿐 아니라 동시성 제어와 잠금 경합에도 큰 영향을 준다.