본문 바로가기
Database

[Database] MySQL 잠금(Lock) MySQL 엔진 레벨 잠금 편

by doodoom 2023. 1. 12.

0. 이 글을 쓰게 된 이유

MySQL 잠금에 대해서 공부하던 중 새롭게 안 지식과 전체적인 내용을 정리하기 위해 이 글을 쓰게 되었다.

1. MySQL 엔진의 잠금

MySQL에서 사용되는 잠금은 크게 MySQL 엔진 레벨과 스토리지 엔진 레벨로 나눌 수 있다(MySQL 엔진은 MySQL 서버에서 스토리지 엔진을 제외한 나머지 부분으로 이해하면 됨). MySQL 엔진 레벨의 잠금은 모든 스토리지 엔진에 영향을 미치지만, 스토리지 엔진 레벨의 잠근은 스토리지 엔진 간 상호 영향을 미치지 않는다.
MySQL 엔진 레벨 잠금은 크게 글로벌 락, 테이블 락, 네임드 락, 메타데이터 락이 있다. 그리고 스토리지 엔진 레벨의 락은 사실 상 INNODB 엔진의 락이라고 봐야한다. 왜냐하면 MyISAM과 MEMORY 엔진은 자체적인 락 기능을 가지고 있지않기 때문이다. INNODB 엔진의 락에 대해서는 다음 글에서 설명하겠다. MySQL 엔진 레벨 잠금에 대해서 알아보자.

2. 글로벌 락

글로벌 락은 MySQL 서버의 모든 변경 작업을 멈추는 락이다. FLUSH TABLES WITH READ LOCK으로 획득할 수 있으며, MySQL에서 제공하는 잠금 가운데 가장 범위가 크다. 일단 한 세션에서 글로벌 락을 획득하면 다른 세션에서 SELECT를 제외한 대부분의 DDL 문장이나 DML 문장을 실행하는 경우 글로벌 락이 해제될 떄까지 해당 문장이 대기 상태로 남는다. 글로벌 락이 영향을 미치는 범위는 MySQL 서버 전체이며, 작업 대상 테이블이나 데이터베이스가 다르더라도 동일하게 영향을 미친다.
여러 데이터베이스에 존재하는 MyISAM이나 MEMORY 테이블에 대해 mysqldump로 일관된 백업을 받아야 할 때는 글로벌 락을 사용하게 된다. 하지만 MySQL 서번가 업그레이드 되면서 MyISAM이나 MEMORY 엔진보다는 InnoDB 스토리지 엔진의 사용이 일반화 됐다(MySQL 8.0 부터는 InnoDB가 기본 스토리지 엔진으로 채택됨). InnoDB 스토리지 엔진은 트랜잭션을 지원하기 때문에 일관된 데이터 상태를 위해 모든 데이터 변경 작업을 멈출 필요가 없다. 이러한 이유로 조금 더 가벼운 글로벌 락의 필요성이 생겼고, MySQL 8.0부터는 Xtrabackup이나 Enterprise Backup과 같은 백업 툴들의 안정적인 실행을 위해 백업 락이 도입됐다. 백업 락에 대해서 간단하게 살펴보자.

2.1 백업 락

백업 락은 다음과 같이 획득할 수 있다.

mysql> LOCK INSTANCE FOR BACKUP;
-- // 백업 실행
mysql> UNLOCK INSTANCE;

특졍 세션에서 백업 락을 획득하면 모든 세션에서 다음과 같이 테이블의 스키마나 사용자의 인증 관련 정보를 변경할 수 없게된다.

  • 데이터베이스 및 테이블 등 모든 객체 생성 및 변경, 삭제
  • REPAIR TABLE과 OPTIMIZE TABLE 명령
  • 사용자 관리 및 비밀번호 변경
    하지만 백업 락은 일반적인 테이블의 데이터 변경은 허용된다.

3. 테이블 락

테이블 락은 개별 테이블 단위로 설정되는 잠금이며, 명시적 또는 묵시적으로 특정 테이블의 락을 획득할 수 있다. 테이블 락은 MyISAM 뿐만 아니라 InnoDB 엔진에서도 동일하게 설정할 수 있다.

3.1 테이블 락 명시적 잠금

명시적으로는 "LOCK TABLES table_name [ READ | WRITE ]" 명령으로 특정 테이블의 락을 획득할 수 있다. 명시적으로 획득한 잠금은 UNLOCK TABLES 명령으로 잠금을 반납할 수 있다.
명시적으로 테이블을 잠그는 작업은 특별한 상황이 아니라면 애플리케이션에서 사용할 필요가 거의 없다. 명시적으로 테이블을 잠그는 작업은 글로벌 락과 동일하게 온라인 작업에 상당한 영향을 미치기 때문이다.

3.2 테이블 락 묵시적 잠금

묵시적인 테이블 락은 MyISAM이나 MEMORY 테이블에 데이터를 변경하는 쿼리를 실행하면 발생한다. MySQL 서버가 데이터가 변겨오디는 테이블에 잠금을 설정하고 데이터를 변경한 후, 즉시 잠금을 해제하는 형태로 사용된다. 즉, 묵시적인 테이블 락은 쿼리가 실행되는 동안 자동을 획득 됐다가 쿼리가 완료된 후 자동 해제된다.
하지만 InnoDB 테이블의 경우 스토리지 엔진 차원에서 레코드 기반의 잠금을 제공하기 때문에 단순 데이터 변경 쿼리로 인해 묵시적인 테이블 락이 설정되지 않는다. 더 정확히는 InnoDB 테이블에도 테이블 락이 설정되지만 대부분의 데이터 변경(DML) 쿼리에서는 무시되고 스키마를 변경하는 쿼리(DDL)의 경우에만 영향을 미친다.

4. 네임드 락

네임드 락은 GET_LOCK() 함수를 이용해 임의의 문자열에 대해 잠금을 설정할 수 있다. 이 잠금의 특징은 대상이 테이블이나 레코드 또는 AUTO_INCREMENT와 같은 데이터베이스 객체가 아니라는 것이다. 네임드 락은 단순히 사용자가 지정한 문자열(String)에 대해 획득하고 반납(해제)하는 잠금이다. 네임드 락은 자주 사용되지는 않지만, 여러 웹서버가 연결 되어있는 상황에서 각 웹서버가 어떤 정보를 상호 동기화해야 하는 상황에서 사용되곤 한다. 사용법은 MySQL DOCS를 참고하길 바란다.

5. 메타데이터 락

메타데이터 락은 데이터베이스 객체(테이블이나 뷰 등)의 이름이나 구조를 변경하는 경우에 획득하는 잠금이다. 메타데이터 락은 명시적으로 획득하거나 해제할 수 있는 것이 아니고 RENAME TABLE 명령 같은 경우 자동으로 획득하는 잠금이다.

6. 정리

간단하게 MySQL 엔진 레벨 잠금에 어떤 종류가 있는지 살펴보았다. 각 락에 대해서 자세하게 공부하려면 MySQL 공식 문서나 Real MySQL을 읽는 것을 추천한다. 다음 글에서는 레코드 단위로 락을 걸 수 있는 InnoDB 스토리지 엔진 락에 대해서 알아보겠다.