🎯 스토리지 엔진 수준의 락 종류
스토리지 엔진 락(Storage Engin Locks) 은 InnoDB, MyISAM 등 스토리지 엔진이 자체적으로 관리하는 락을 의미 합니다. 데이터 읽기, 쓰기, 트랜잭션 제어가 동작할때 적용되고 데이터 정합성과 동시성을 제어하기 위해 내부적으로 처리하는 락 메커니즘 입니다. 대부분의 경우 InnoDB 엔진을 사용하므로 해당 포스팅에서는 InnoDB 기준으로 설명드리겠습니다.
MYSQL 서버는 SQL 쿼리를 파싱하고 실행 계획을 세우며, 스토리 엔진은 실제 데이터에 접근하고 락을 관리합니다. 즉, 스토리 엔진 락 == 데이터 자체에 대한 잠금을 의미합니다.
총 4 락이 존재합니다.
1. 레코드 락(Recor Lock)
2. 갭 락 (Gap Lock)
3.넥스트 키 락 (Next Key Lock)
4. 자동 증가 락(Auto Increment Lock)
✅ 레코드 락 (Record Lock)
행 단위로 락을 거는 방식입니다. UPDATE, DELETE, SELECT ... FOR UPDATE 등에서 사용되고 높은 동시성을 지원하는 것이 특징입니다. 일반적으로 레코드 락은 테이블 레코드 자체를 잠그는 락을 의미합니다. 하지만 MySQL 에서의 레코드 락은 테이블 레코드가 아닌, 인덱스에 대한 레코드를 잠그는 것이 특징 입니다.
테이블이 아니라, 인덱스에만 락을 거는 이유는 효율적이고 정밀한 락을 관리할 수 있기 때문입니다. WHERE 조건으로 행을 조회할 때, 어떤 행들에 대해 락을 걸어야 하는지 판단하려면 인덱스를 활용해야 합니다. 인덱스가 없다면 전체 테이블 스캔 후 어떤 레코드가 해당되는지를 판단해야 하므로 정확한 락 타켓 지정이 어렵습니다. 때문에 MySQL 에서는 인덱스를 기준으로 락을 걸어야 특정 행이나 구건에 정확하게 락을 걸 수 있습니다.
하지만,인덱스를 따로 걸어주지 않으면 MySQL 에서는 테이블을 상대로 풀스캔 작업이 진행되므로 MySQL 에서 인덱스 설계는 매우 중요합니다.
✅ 갭 락 (Gap Lock)
갭 락은 말 그대로 데이터와 데이터 사이의 공간(갭)에 걸리는 락 입니다. 즉, 어떤 레코드 하나에 락을 거는 것이 아니라, 존재하지 않는 값의 구간에 락을 거는 것입니다. 갭 락은 주로 다음과 같은 상황에서 적용됩니다.
- 범위 조건 쿼리 (BETWEEN, > , < ) + FOR UPDATE
- 트랜잭션 격리 수준이 REPEATABLE READ
InnoDB 는 기본적으로 REPEATABLE READ 격리 수준에서 팬덤 리드 (Phantom Read) 를 방지하기 위해 갭락을 사용합니다. 그렇다면 이러한 갭 락이 왜 필요할까 ?
한 트랜잭션에서 동일한 조건으로 두번의 SELECT 쿼리를 날렸을때, 처음에는 없던 행이 두번째에 나타내는 이상 현상 ( Phantom Read ) 를 막기 위해 갭락이 사용됩니다.
예제를 통해 자세히 알아봅시다.
users 테이블 생성
CREATE TABLE users (
id INT PRIMARY KEY,
age INT
) ENGINE=InnoDB;
INSERT INTO users (id, age) VALUES
(1, 20),
(2, 25),
(3, 30),
(4, 35);
트랜잭션A : 갭락 설정
-- 트랜잭션 A 시작
START TRANSACTION;
-- 25 ~ 30 사이의 레코드를 FOR UPDATE (잠금)
SELECT * FROM users WHERE age > 25 AND age < 30 FOR UPDATE;
위에서 범위 조건 쿼리 (BETWEEN, > , < ) + FOR UPDATE 가 실행될때 갭락이 설정된다 말씀드렸습니다. 이 쿼리는 팬덤 리드를 방지하기 위해 25 와 30 사이의 갭 전체에 락을 겁니다.
트랜잭션B : 삽입 시도 (실 패)
-- 트랜잭션 B 시작
START TRANSACTION;
-- 갭 안에 새로운 값 삽입 시도
INSERT INTO users (id, age) VALUES (5, 27);
트랜잭션 B 는 트랜잭션 A 의 갭 락이 해제되기 전 까지 해당 갭에 데이터를 삽입할 수 없습니다.
즉 갭락은 존재하지 않는 레코드에도 락이 걸립니다. 갭 락은 삽입만 막고 기존의 레코드 수정은 허용하며 동시성은 떨어뜨리지만, 정합성을 보장하는 것이 특징 입니다.
이와 같은 원리로 실행되는 갭락은 팬덤 리드 (Phantom Read) 현상이 발생하지 않도록 정합성을 보장합니다. 하지만 너무 많은 갭 락은 동시성에 악 영향을 줄 수 있으므로, 불필요한 범위 쿼리와 락 설정은 피하는 것이 좋습니다.
✅ 넥스트 키 락 (Next - Key Lock)
넥스트 키 락은 레코드 락과 갭락을 합친 락 입니다. 즉, 해당 인덱스 레코드와 그 바로 앞 갭에 락을 거는 방식이죠. 이를 통해 레코드 자체와 그 주변의 갭 까지 함께 포호해 팬덤 리드를 방지하고 레코드 중복 삽입도 막을 수 있습니다.
-- age가 25인 레코드가 존재할 때,
SELECT * FROM users WHERE age = 25 FOR UPDATE;
이 쿼리는 단순히 a = 25 에 해당하는 레코드 뿐만 아니라 25 이전 갭에도 락을 설정합니다. 이러한 방식으로 인해 레코드 수정, 삭제를 방지하고 해당 위치에 새로운 레코드 삽입을 방비합니다.
InnoDB 의 기본 격리 수준인 REPEATABLE READ 에서는 대부분의 상황에서 넥스트 키 락이 기본으로 사용됩니다.
✅ 자동 증가 락 (Auto-Increment Lock)
Auto_INCREMENT 속성이 있는 컬럼에 값을 삽입할때 MySQL 은 자동 증가 값을 생성하고 이를 테이블에 저장하기 위해 락을 사용합니다. InnoDB 는 기본적으로 테이블 수준의 락을 이용해 자동 증가 값을 제어 합니다.
이러한 락은 여러 트랜잭션이 동시에 INSERT 가 수행될 때 자동 증가 키가 중복되거나 건너 뛰는 현상을 방지 합니다.
INSERT INTO users (name) VALUES ('Tom'); -- id = 1
INSERT INTO users (name) VALUES ('Jane'); -- id = 2
위 두 쿼리가 동시에 수행된다 해도 InnoDB 는 내부적ㅇ로 자동 증가 값 계산 및 저장 시점에 잠깐 락을 걸어 충돌을 방지합니다.
지금껏 알아본 락에 대해 정리하면 다음과 같습니다.
락 종류 | 설명 | 주요 특징 |
Record Lock | 특정 레코드(인덱스)에 락 | 높은 동시성, 인덱스 기반 |
Gap Lock | 존재하지 않는 값의 구간에 락 | 팬텀 리드 방지, 삽입만 차단 |
Next-Key Lock | 레코드 + 앞 갭에 락 | 팬텀 리드 방지, 중복 삽입 차단 |
Auto-Increment Lock | 자동 증가 키를 위한 테이블 락 | 중복/건너뛰기 방지 |
'데이터베이스' 카테고리의 다른 글
[Database] 전체 텍스트 인덱스(Full-Text Index) 에 대해 알아보자 (0) | 2025.05.07 |
---|---|
[Database] 커버링 인덱스를 이용한 페이징 성능 개선 (0) | 2025.05.05 |
[Database] No Offset 를 이용한 페이징 조회 개선하기 (0) | 2025.05.04 |
[Database] DB 인덱스를 이용한 성능 개선 (0) | 2025.05.02 |
트랜잭션 격리 수준에 대해 알아보자 (0) | 2025.05.02 |