우아한테크코스 레벨 4 팀 프로젝트 festabook에서 학습한 내용을 정리한 글입니다.
💭 들어가며
동시성 문제를 계기로 Lock에 대해 공부하면서, 공식 문서, 책, 블로그 등을 살펴보았다. 그러나 자료마다 설명이 제각각이었고, Real MySQL 8.0의 설명조차 MySQL 공식 문서와 다른 부분이 존재했다. 이는 DBMS마다 지원하는 Lock의 세부 종류와 동작 방식이 달라, 통일된 기준 문서를 찾기 어렵기 때문이다. 이번 글에서는 SQL 표준 문서를 기준으로 Lock의 전체적인 범위를 먼저 정리하고, 이후 글에서는 MySQL에 특화된 Lock 내용을 다룰 예정이다.
✅ Lock 지원 단위
🔽 참고
SQL 표준 문서에서 정의하는 Lock의 지원 단위는 Table과 Row에 한정된다. 그 외 Page/Block, Index, Database 수준의 Lock은 Oracle, SQL Server, MySQL 등 각 DBMS가 자체적으로 확장하여 제공한다.
예를 들어, SQL Server는 RID, Page, Extent, HoBT, Table 단위 Lock을 지원하고, MySQL(InnoDB)는 Global 단위를 추가로 제공한다. 따라서 실제 사용 가능한 Lock 단위는 DBMS 공식 문서를 반드시 확인해야 한다.
▶ 데이터베이스(Database)
데이터베이스 단위로 Lock을 설정하는 방식이다.
- 해당 DB 내 모든 테이블과 레코드에 대한 접근이 차단된다.
- 주로 유지보수, 백업, 대규모 스키마 변경 같은 특수 상황에서만 사용된다.
- 동시성이 심각하게 제한되므로 일반적인 환경에서는 거의 사용되지 않는다.
🔽 참고
MySQL의 Global Lock이 이에 해당된다.
▶ 파일(File)
테이블이나 인덱스가 저장된 물리적 파일 단위로 Lock을 설정하는 방식이다.
- 파일 기반 DBMS 또는 구버전에서 주로 사용되었다.
- 최신 DBMS에서는 더 세밀한 Lock 단위를 선호하기 때문에 잘 쓰이지 않는다.
🔽 참고
MySQL의 MyISAM 스토리지 엔진이 파일 단위 Lock을 사용했다.
▶ 테이블(Table)
테이블 단위로 Lock을 설정하는 방식이다.
- 테이블 내 모든 레코드가 동시에 수정 불가 상태가 된다.
- 쓰기 작업이 많을 경우 동시성이 크게 저하될 수 있다.
▶ 페이지(Page) (= Block)
DB 저장소에서 일정 크기(보통 4KB~16KB)의 데이터 묶음인 페이지 단위로 Lock을 설정하는 방식이다.
- 행보다 크고, 테이블 전체보다는 작은 단위다.
- 여러 행이 같은 페이지에 속해 있으면, 특정 행이 Lock될 때 페이지 전체가 함께 잠길 수 있다.
🔽 참고
- SQL Server, Oracle은 Page 단위 Lock을 지원한다.
- MySQL(InnoDB)는 직접적인 Page Lock 대신 Row Lock + Gap Lock 조합을 사용한다.
▶ 행(Row)
행 단위로 Lock을 설정하는 방식이다.
- 가장 세밀하게 제어할 수 있어 동시성 확보에 유리하다.
- 하지만 관리해야 할 Lock의 수가 많아져 성능 부담이 커질 수 있다.
▶ 컬럼(Column)
특정 행의 일부 컬럼 단위로 Lock을 설정하는 방식이다.
- 이론적으로는 가능하지만, 구현 난이도가 높고 실질적 효용이 낮아 상용 DBMS에서는 거의 사용되지 않는다.
✅ Lock 종류
SQL-92에서는 트랜잭션 격리 수준을 구현하기 위해 Lock 모드를 정의한다. SQL-92에는 공유 락(Shared), 배타 락(Exclusive), 내재 락(Intent) 등이 정의되어 있으며, 업데이트 락(Update)은 SQL Server 확장 기능이다.
▶ 공유 락(Shared Lock, S)
데이터를 조회(SELECT)할 때 사용하며, S로 표기한다.
- 다른 트랜잭션도 동일한 데이터에 대해 공유 락(S)을 걸 수 있다. 즉, 읽기는 여러 트랜잭션에서 동시에 가능하다.
- 그러나 다른 트랜잭션이 배타 락(X)을 거는 것은 허용되지 않는다. 즉, 쓰기는 불가능하다.
▶ 배타 락(Exclusive Lock, X)
데이터를 변경(INSERT, UPDATE, DELETE)할 때 사용하며, X로 표기한다.
- 해당 데이터에 대해 다른 어떤 트랜잭션도 공유 락(S)이나 배타 락(X)을 걸 수 없다.
- 즉, 읽기와 쓰기 모두 차단된다.
▶ 업데이트 락(Update Lock, U)
데이터를 수정하기 위해 배타 락(X)을 걸기 전에 사용하며, U로 표기한다.
- 공유 락(S)에서 배타 락(X)으로 승격하는 과정에서 Deadlock이 자주 발생한다.
- 이를 방지하기 위해 중간 단계로 Update Lock을 사용한다.
🔽 참고
ANSI SQL 표준에는 Update Lock이라는 용어 자체는 존재하지 않는다. Microsoft SQL Server 등 일부 DBMS에서 Deadlock 회피 목적으로 추가로 제공하는 락 모드다.
▶ 내재 락(Intent Lock, IS, IX, SIX)
상위 객체(테이블)에 직접 Lock을 걸지 않고도, 하위 객체(행, 페이지) 단위 Lock을 명확히 알리기 위해 사용하며, IS, IX, SIX로 표기한다.
- 계층적 구조(Database → Table → Page → Row)에서 DBMS가 Lock 충돌 여부를 빠르게 판별할 수 있도록 한다.
- 직접 데이터를 보호하는 Lock이 아니라, Lock 관리 최적화를 위한 의도 표시 역할을 한다.
- 종류
- IS (Intent Shared): 테이블 내 특정 행에 공유 락(S)을 걸 예정이라는 의도를 표기한다.
- IX (Intent Exclusive): 테이블 내 특정 행에 배타 락(X)을 걸 예정이라는 의도를 표기한다.
- SIX (Shared with Intent Exclusive): 테이블 전체에는 공유 락(S)을 걸고, 특정 행에는 배타 락(X)을 걸 예정이라는 의도를 표기한다.
🎬 마무리하며
이론적인 표준 관점에서 Lock을 학습했을 때, 다소 추상적으로 느껴졌다. 따라서 다음 글에서는 내가 주로 사용하는 MySQL(InnoDB)를 기준으로, 구체적인 예시와 함께 Lock이 실제로 어떻게 동작하는지 정리할 예정이다.
📍 참고 자료
'Backend > Database' 카테고리의 다른 글
| [Database] 인덱스(Index) (1) (0) | 2025.10.14 |
|---|---|
| [Database] MySQL(InnoDB) 락(Lock) (2) (2) | 2025.10.06 |
| [Database] 동시성 문제(Read 계열), 트랜잭션 격리 수준 (1) | 2025.10.01 |
| [Database] MySQL 100만 건 데이터 삽입하기 (0) | 2025.09.28 |
| [Database] 데이터베이스 무중단 마이그레이션 (2) | 2025.08.27 |