테마
MySQL 엔진의 잠금
MySQL은 SQL을 해석하고 실행하는 서버 층과, 데이터를 실제로 디스크에 저장하고 읽어 오는 스토리지 엔진(storage engine) 층으로 나뉜다. 이 문서는 어떤 스토리지 엔진을 쓰든 MySQL 서버 층에서 거는 잠금을 다룬다. 글로벌 락(global lock)·테이블 락(table lock)·네임드 락(named lock)·메타데이터 락(metadata lock) 네 가지만 알면 된다. 행 하나하나에 거는 잠금 이야기는 InnoDB 잠금 문서에서 다룬다.
네 가지 잠금
앞의 세 잠금은 사용자가 명령으로 직접 걸고 푼다. 메타데이터 락은 DML(Data Manipulation Language, 데이터 조작어)이나 DDL(Data Definition Language, 데이터 정의어)을 실행할 때 서버가 자동으로 걸고, 문장이나 트랜잭션(transaction)이 끝나면 자동으로 푼다.
| 잠금 | 범위 | 거는 법 | 푸는 법 |
|---|---|---|---|
| 글로벌 락 | 서버 전체 읽기 | FLUSH TABLES WITH READ LOCK | UNLOCK TABLES / 세션1 종료 |
| 테이블 락 | LOCK TABLES 한 테이블 | LOCK TABLES t READ/WRITE | UNLOCK TABLES / 세션 종료 / 트랜잭션 시작 |
| 네임드 락 | 임의 문자열 이름 | GET_LOCK('이름', 타임아웃) | RELEASE_LOCK('이름') |
| 메타데이터 락 | 스키마 객체2 | DML·DDL 실행 시 자동 | 문장·트랜잭션 종료 시 자동 |
왜 네 가지인가 — 목적이 다르다
- 글로벌 락: 서버 전체의 변경을 잠시 멈춰야 하는 백업·스냅샷(snapshot) 작업에 쓴다. InnoDB 테이블만 논리 백업(logical backup)한다면
mysqldump --single-transaction으로 글로벌 락을 대부분 피할 수 있다. 이 옵션은 백업 전체를 트랜잭션 하나로 묶어, 잠그지 않고도 한 시점의 데이터를 읽기 때문이다. 하지만 트랜잭션을 지원하지 않는 테이블이나 파일 단위 복사까지 일관성을 맞출 때는 별도 잠금 전략이 필요하다. - 테이블 락: 행 단위로 잠글 수 없던 MyISAM 시절의 유산이고, 지금은 사용자가 명시적으로 테이블을 막아야 할 때 쓴다. InnoDB 테이블에도 걸 수 있다. 하지만 InnoDB에는 행 잠금이 있는데 굳이 테이블 전체를 잠그면, 다른 세션이 그 테이블을 동시에 쓸 수 없어 동시성을 스스로 버리게 된다.
- 네임드 락: 사용자가 정한 문자열 이름에 거는 잠금이다. 한 MySQL 서버 인스턴스가 제공하는 권고형 잠금(advisory lock)로, 데이터를 실제로 막지 않고 같은 이름을 요청하는 쪽끼리만 차례를 기다리게 한다. 그래서 "이 배치 작업은 여러 서버 중 한 노드에서만 돌린다" 같은 애플리케이션 수준 조율에 쓸 수 있다. 다만 클러스터 전체의 합의 장치나 트랜잭션 잠금은 아니다.
GET_LOCK은 1이면 획득, 0이면 타임아웃, NULL이면 에러를 뜻하므로 반환값을 반드시 확인한다. - 메타데이터 락: 줄여서 MDL(Metadata Lock, 메타데이터 락)이라 부른다. 테이블 구조를 보호하는 잠금으로, 누가 테이블을 쓰는 동안 구조가 바뀌지 않게 한다.
SELECT가 실행 중인 테이블에ALTER가 오면 ALTER는 SELECT 쪽이 MDL을 놓을 때까지 기다린다. 그리고 기다리는 DDL 뒤에 들어온 쿼리들은 그 DDL에 막혀 줄줄이 밀린다. "어느 날 갑자기 전부 느려졌다"는 장애의 단골 원인이다.
MDL 대기 한 장면
다이어그램 로딩…
SELECT 문장이 끝났더라도 그 트랜잭션이 열려 있으면 MDL은 커밋(commit)이나 롤백(rollback)까지 유지될 수 있다. 이런 트랜잭션 하나가 DDL을 막고, 대기 중인 DDL이 뒤 요청까지 막는 연쇄가 생긴다. 기다리는 쿼리마다 DB 연결(커넥션)을 하나씩 붙잡으므로, 대기가 쌓이면 쓸 수 있는 커넥션이 바닥나 장애로 번진다. 실행 중인 접속 목록을 보여 주는 SHOW PROCESSLIST에서 MDL을 기다린다는 상태 Waiting for table metadata lock이 보이면, 열린 트랜잭션과 대기 큐를 함께 확인한다. 막는 트랜잭션을 찾는 조회는 온라인 DDL 3·온라인 DDL 4에서, 온라인 DDL(online DDL)이 MDL을 언제 잡는지와 대기 한도 lock_wait_timeout을 줄여 두는 대처는 온라인 DDL 2에서 본다.
면접 포인트
- "글로벌 락과 테이블 락의 차이?" → 범위(서버 전체 vs 지정 테이블). 둘 다
UNLOCK TABLES로 푼다는 공통점도 언급. - "MDL이 뭐예요?" → 스키마 일관성용 자동 잠금 + 대기 연쇄 장면을 그려주면 합격점.
- "GET_LOCK은 언제 써요?" → DB 밖 조율(배치 중복 실행 방지). 애플리케이션 락과 DB 락의 경계를 아는지 본다.
참고
