한 줄 정의
MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향 을 미치며, 글로벌 락, 백업 락, 테이블 락, 네임드 락, 메타데이터 락의 5가지가 있습니다.
쉽게 말하면
MySQL 엔진의 잠금은 건물 전체의 보안 시스템이고, InnoDB의 잠금은 각 사무실의 자물쇠입니다. 건물 보안(MySQL 엔진 잠금)이 잠기면 모든 사무실에 영향을 미치지만, 한 사무실의 자물쇠(InnoDB 잠금)는 다른 사무실에 영향을 주지 않습니다.
핵심 내용
글로벌 락 (Global Lock)
MySQL에서 제공하는 가장 범위가 큰 잠금 입니다.
FLUSH TABLES WITH READ LOCK;- 한 세션에서 글로벌 락을 획득하면, 다른 세션에서 SELECT를 제외한 대부분의 DDL/DML이 대기 상태가 됩니다
- 영향 범위가 MySQL 서버 전체이므로, 작업 대상 테이블이나 데이터베이스가 다르더라도 동일하게 영향을 미칩니다
mysqldump가 내부적으로 이 명령을 실행할 수 있으므로, 백업 옵션을 반드시 확인해야 합니다
글로벌 락의 위험성
글로벌 락을 걸기 전에 장시간 실행 중인 쿼리가 있으면, 그 쿼리가 종료될 때까지 글로벌 락 자체가 대기합니다. 이 과정에서 새로운 DML도 모두 블로킹되므로, 최악의 경우 서버 전체의 INSERT/UPDATE/DELETE가 장시간 멈출 수 있습니다.
백업 락 (Backup Lock) — MySQL 8.0+
글로벌 락의 무거움을 보완하기 위해 도입된 경량화된 잠금 입니다.
LOCK INSTANCE FOR BACKUP;
-- 백업 실행
UNLOCK INSTANCE;글로벌 락 vs 백업 락
| 기준 | 글로벌 락 | 백업 락 |
|---|---|---|
| DML (INSERT/UPDATE/DELETE) | 차단 | 허용 |
| DDL (스키마 변경) | 차단 | 차단 |
| 사용자 관리 | 차단 | 차단 |
| 복제 영향 | 복제 지연 발생 | 복제 정상 진행 |
| 도입 버전 | MySQL 5.0 이전 | MySQL 8.0 |
| 주요 사용처 | MyISAM 백업 | InnoDB 백업 (XtraBackup 등) |
백업 락의 핵심 가치는 복제가 정상 진행되면서 백업 중 DDL만 차단 하는 것입니다. XtraBackup이나 Enterprise Backup 실행 중 스키마 변경이 발생하면 백업이 실패하는데, 백업 락이 이를 방지합니다.
테이블 락 (Table Lock)
개별 테이블 단위로 설정되는 잠금입니다.
-- 명시적 테이블 락
LOCK TABLES table_name [READ | WRITE];
UNLOCK TABLES;- 명시적 테이블 락 은 온라인 작업에 큰 영향을 미치므로, 특별한 상황이 아니면 사용하지 않습니다
- 묵시적 테이블 락 은 MyISAM/MEMORY 테이블에서 DML 실행 시 자동으로 획득/해제됩니다
- InnoDB는 레코드 기반 잠금을 사용하므로, 단순 DML에서는 묵시적 테이블 락이 설정되지 않습니다. DDL에서만 영향 을 받습니다
네임드 락 (Named Lock)
임의의 문자열 에 대해 잠금을 설정하는 기능입니다. 테이블이나 레코드가 아닌, 사용자가 정의한 문자열에 대한 잠금입니다.
-- 잠금 획득 (2초 대기 후 자동 해제)
SELECT GET_LOCK('mylock', 2);
-- 잠금 상태 확인
SELECT IS_FREE_LOCK('mylock');
-- 잠금 해제
SELECT RELEASE_LOCK('mylock');활용 사례
- 여러 웹 서버 간 동기화 : DB 서버 1대에 웹 서버 5대가 접속하는 환경에서, 동일 작업의 동시 실행을 방지
- 배치 프로그램의 데드락 방지 : 동일 데이터를 변경하는 배치끼리 분류해서 네임드 락을 걸면 데드락을 회피할 수 있음
MySQL 8.0부터는 네임드 락을 중첩 해서 사용할 수 있으며, RELEASE_ALL_LOCKS()로 한 번에 모두 해제할 수 있습니다.
메타데이터 락 (Metadata Lock)
데이터베이스 객체(테이블, 뷰 등)의 이름이나 구조를 변경할 때 자동으로 획득 되는 잠금입니다.
-- 올바른 방법: 하나의 RENAME에서 두 테이블을 동시에 변경
RENAME TABLE rank TO rank_backup, rank_new TO rank;위와 같이 한 문장에서 처리하면 rank 테이블이 존재하지 않는 순간이 생기지 않습니다.
-- 잘못된 방법: 두 개의 RENAME으로 분리
RENAME TABLE rank TO rank_backup; -- 이 순간 rank가 없음!
RENAME TABLE rank_new TO rank;대용량 테이블 구조 변경 실전 패턴
Online DDL이 너무 오래 걸리는 경우, 새 테이블을 만들고 데이터를 복사한 뒤 RENAME하는 방법을 사용합니다:
-- 1. 새 구조의 테이블 생성
CREATE TABLE access_log_new (...) KEY_BLOCK_SIZE=4;
-- 2. 여러 스레드로 데이터 복사 (id 범위별 분할)
-- thread1: INSERT INTO access_log_new SELECT * FROM access_log WHERE id>=0 AND id<10000;
-- thread2: INSERT INTO access_log_new SELECT * FROM access_log WHERE id>=10000 AND id<20000;
-- ...
-- 3. 나머지 데이터 복사 + RENAME (서비스 중단 최소화)
SET autocommit=0;
LOCK TABLES access_log WRITE, access_log_new WRITE;
SELECT MAX(id) as @MAX_ID FROM access_log_new;
INSERT INTO access_log_new SELECT * FROM access_log WHERE pk > @MAX_ID;
COMMIT;
RENAME TABLE access_log TO access_log_old, access_log_new TO access_log;
UNLOCK TABLES;
-- 4. 정리
DROP TABLE access_log_old;이 패턴의 핵심은 잠금 시간을 최소화 하기 위해 대부분의 데이터를 미리 복사해두고, 마지막 소량의 데이터만 잠금 상태에서 복사하는 것입니다.
내 생각
-
mysqldump를 무심코 실행하면 내부적으로 글로벌 락이 걸릴 수 있습니다.--single-transaction옵션(InnoDB 전용)을 사용하면 글로벌 락 없이 일관된 백업이 가능합니다. -
메타데이터 락을 이용한 대용량 테이블 구조 변경 패턴은 실무에서 매우 유용합니다. pt-online-schema-change나 gh-ost 같은 도구도 결국 이 패턴을 자동화한 것입니다.
관련 개념
- Ch05-3 InnoDB 스토리지 엔진 잠금 — 스토리지 엔진 레벨의 레코드 기반 잠금
- Ch04-2 InnoDB 스토리지 엔진 — InnoDB의 내부 구조
출처
- Real MySQL 8.0 (1권), 5.2 MySQL 엔진의 잠금