본문 바로가기
ComputerScience/RealMySQL

5.트랜잭션과 잠금 - InnoDB 스토리지 엔진 잠금

by 규난 2022. 12. 11.
728x90

이번 포스트에서는 InnoDB 스토리지 엔진 잠금의 종류에 대해서 알아보도록 하겠습니다.

 

InnoDB 스토리지 엔진 잠금

InnoDB 스토리지 엔진은 MySQL에서 제공하는 잠금과는 별개로 레코드 기반의 잠금을 탑재하고 있습니다.

레코드 기반의 잠금을 제공하기 때문에 다른 스토리지 엔진보다 훨씬 뛰어난 동시성 처리를 제공합니다.

 

MySQL 서버의 information_schema 데이터베이스에 존재하는 INNODB_TRX, INNODB_LOCKS, INNODB_LOCKS_WAITS 테이블을 조인해서 어떤 잠금이 대기하고 있고 해당 잠금을 어떤 트랜잭션이 가지고 있는지 확인이 가능하며 장시간 잠금을 가지고 있는 클라이언트를 찾아서 종료시킬 수 있습니다.

 

InnoDB 잠금의 종류

레코드 락(Record Lock)

레코드 락은 레코드 자체만 잠그는 것입니다.

InnoDB 스토리지 엔진은 레코드 자체가 아니라 인덱스의 레코드를 잠그게 됩니다.

만약 인덱스가 하나도 없는 테이블이더라도 내부적으로 자동으로 생성된 클러스터 인덱스를 이용해 잠금을 설정하게 됩니다.

 

갭 락(Gap Lock)

갭 락은 레코드 자체가 아니라 레코드와 인접한 레코드 사이의 잠금을 걸어 그 사이의 새로운 Insert가 생성되는 것을 제어합니다.

 

넥스트 키 락(Next Key Lock)

넥스트 키 락은 레코드 락과 갭 락을 합쳐놓은 형태입니다.

InnoDB 스토리지 엔진의 넥스트 키 락은 바이너리 로그에 기록되는 쿼리가 레플리카 서버(백업 서버)에서 실행될 때 소스 서버에서 만들어 낸 결과와 동일한 결과를 만들어 내도록 보장하기 위한 목적으로 사용됩니다.

 

InnoDB 스토리지 엔진에서 대부분 보조 인덱스를 이용한 변경 작업은 넥스트 키 락 또는 갭 락을 사용하지만 프라이머리 키 또는 유니키 인덱스에 의한 변경은 레코드 자체에 대해서만 락을 걸게 됩니다.

 

자동 증가 락(Auto Increment Lock)

MySQL에서는 자동 증가하는 숫자 값을 추출하기 위해서 AUTO_INCREMENT라는 형태의 컬럼 속성을 제공합니다.

이 컬럼 속성이 사용된 테이블에 동시에 여려 레코드가 INSERT 되는 경우 저장되는 레코드는 중복되지 않고 저장된 순서대로 증가하는 일련번호를 가져하기 때문에 InnoDB 스토리지 엔진은 내부적으로 Auto Increment Lock을 사용해 테이블 수준의 잠금을 사용하게 됩니다.

 

Auto Increment Lock은 INSERT와 REPLACE 쿼리 문장과 같이 새로운 레코드를 저장하는 쿼리에만 필요하며, UPDATE나 DELETE 쿼리에서는 걸리지 않습니다. 또한 트랜잭션과 관계없이 INSERT나 REPLACE 문장에서 AUTO_INCREMENT 값을 가져오는 순간에만 락을 걸었다가 즉시 해지되며(아주 짧은 시간 동안 걸리는 락이므로 대부분의 경우 문제가 없음) 명시적으로 획득하고 해지하는 방법은 없습니다. 마지막으로 Auto Increment Lock은 테이블에 단 하나만 존재하기 때문에 여러 개의 INSERT 쿼리가 동시에 들어오면 하나의 쿼리를 제외 한 모든 쿼리는 락을 획득하기 위해 기다려야 합니다.

 

인덱스와 잠금

InnoDB 스토리지 엔진은 레코드 기반의 잠금 기능을 제공하며 레코드 자체가 아니라 인덱스의 레코드를 잠그는 방식으로 처리하게 된다고 위에서 설명드렸습니다. 이 말은 변경해야 할 레코드를 찾기 위해 검색한 인덱스의 레코드를 모두 락을 걸어야 한다는 의미입니다.

 

예를 들어 회원 테이블에 변경하려는 레코드인 별명이 "규난"이고 성이 "한"인 레코드가 1건이 있고

별명이 "규난"인 레코드는 10만 건이 있다면 위에서 1건의 레코드를 변경하기 위해 총 10만 건의 레코드가 락이 걸리게 됩니다.

이렇게 의도하지 않게 많은 레코드의 락이 걸리는 걸 방지하기 위해서 MySQL에서 인덱스 설계를 신중하게 해야 합니다. 

728x90