숑숑이의 개발일기
article thumbnail

실제 Inno DB 내부에서는 여러 트랜잭션들이 경합되고 있는 상황에서 최대한의 성능을 위해 여러 방식의 다양한 락(Lock)을 조합해서 사용하고 있다. 이 과정에서 각 트랜잭션이 획득한 락들은 해당 트랜잭션이 commit/rollback 되어 종료될 때까지 유효한다.

 

MySQL에서의 락의 종류

MySQL에서 사용되는 락은 크게 아래와 같이 나눌 수 있다.

  • 스토리지 엔진 레벨 : 테이블의 데이터를 다루기 위한 락
    • 레코드 락(Record Lock)
    • 갭 락(Gap Lock)
    • 넥스트 키 락(Next Key Lock)
    • 자동 증가 락(Auto Increment Lock)
  • MySQL 엔진 레벨 : 테이블이나 데이터베이스 등과 같은 부분을 위한 락

 

레코드 락(Record Lock)

일반적으로 레코드 락은 테이블 레코드 자체를 잠그는 락을 의미한다. 레코드 수준의 잠금은 상당히 작은 공간으로 관리되기 떄문에 락 에스컬레이션은 없다. 하지만 MySQL에서의 레코드 락은 인덱스의 레코드를 잠근다는 점에 차이가 있다.

락이 걸리는 인덱스는 클러스터 인덱스(PK) 및 논클러스터 인덱스(세컨더리 인덱스) 모두를 포함한다. 만약 PK가 없는 테이블이라면 내부적으로 자동 생성된 PK를 이용해 설정한다.

 

  • 회원(member) 테이블에 성(last_name)이 J로 시작하는 구성원이 300명이 있다 가정.
  • 이름(first_name)이 Syong인 사원은 1명만 존재
  • 성(last_name) 컬럼에 인덱스가 걸려있음
  • 성이 J로 시작하며 이름이 Syong인 구성원의 등록일을 변경하는 UPDATE 쿼리를 실행
UPDATE member SET register_date = now() WHERE last_name LIKE 'J%' AND first_name = 'Syong';

 

UPDATE 문에 의해 영향받는 레코드는 1건이다. 그러나 MySQL은 인덱스에 잠금을 걸기 때문에 1건을 업데이트 하기 위해 300건의 인덱스 레코드에 잠금이 걸린다. 인덱스는 성(last_name)으로만 구성되어 있기 때문에, 해당 레코드를 갱신하기 위해서는 인덱스를 통해 검색되는 모든 레코드에 잠금을 걸게 된다.

 

만약 적당한 인덱스가 없다면 모든 테이블의 레코드에 락을 걸고, 테이블을 풀스캔 하면서 작업을 처리하게 되어 동시성이 상당히 떨어진다. 그렇기 때문에 특히 MySQL에서 인덱스 설계가 중요한 것이다.

레코드 락은 트랜잭션이 DML 구문을 실행할 때 자동으로 거는 락이다. 레코드 락 덕분에 여러 트랜잭션이 동시에 서로 다른 레코드에 접근할 수 있는 것이다.

DML(Data Manipulation Language) - 데이터 조작어
정의된 데이터베이스에 입력된 레코드를 조회, 수정, 삭제 등의 역할을 하는 언어로 SELECT, INSERT, UPDATE, DELETE가 존재한다.

 

 

갭 락(Gap Lock)

레코드가 아닌 레코드와 레코드 사이의 간격을 잠금으로써 레코드의 생성, 수정 및 삭제를 제어한다. 갭 락은 인덱스 범위 조건 중에서 실제 레코드를 제외하고, 데이터가 추가될 수 있는 범위에 걸린다. 인덱스는 정렬된 순서로 존재하므로, 현존하는 레코드의 앞 뒤에 갭 락이 걸린다.

 

  • num 테이블에 2, 3이라는 2개의 인덱스 레코드가 존재
  • 1이상 5이하의 조건으로 데이터를 검색

 

현존하는 레코드인 2와 3에 걸리는 락이 바로 레코드 락이며, 아직 실존하지 않는 1, 4, 5가 추가될 수 있는 공간에 걸리는 락이 갭 락.

 

즉, 지정된 범위에 해당하는 인덱스 테이블 공간을 대상으로 거는 잠금이다. 따라서 데이터의 유일성이 보장되는 PK 또는 유니크 인덱스에 의한 작업에서는 갭 락이 사용되지 않는다. 이러한 갭 락은 유령 읽기(Pantom Read)를 방지하는데 도움이 된다.

 

 

넥스트 키 락(Next Key Lock)

레코드 락과 갭 락을 합친 잠금으로, 위에서 살펴본 갭 락은 단독으로 사용되기 보다 넥스트 키 락의 일부로 함께 사용된다. 변경을 위해 검색하는 레코드에 넥스트 키 락 방식으로 잠금이 걸리면, 해당 레코드에 대해 잠금걸고, 인접 레코드와의 간격에도 잠금을 걸게 된다.

 

 

 

요약

  • Inno DB 스토리지 엔진은 레코드 락(Record Lock), 레코드와 인접 레코드 사이의 간격을 잠그는 갭 락(Gap Lock), 레코드 락과 갭 락을 합쳐놓은 형태의 잠금인 넥스트 키 락(Next Key Lock), 자동 증가 락(Auto Increment Lock)이 존재한다.
  • InnoDB에서는 인덱스에 잠금을 걸기 때문에 인덱스 설계가 중요하다.

 

https://jerry92k.tistory.com/75
https://www.letmecompile.com/mysql-innodb-lock-deadlock/
https://mangkyu.tistory.com/298
profile

숑숑이의 개발일기

@숑숑-

풀스택 개발자 준비중입니다