MySQL에서 사용되는 잠금은 크게 스토리지 엔진
레벨과 MySQL 엔진
레벨로 나눌 수 있다.
스토리지 엔진
레벨의 잠금은 스토리지 엔진 간 상호 영향을 미치지 않는다MySQL 엔진
레벨의 잠금은 모든 스토리지 엔진에 영향을 미친다FLUSH TABLES WITH READ LOCK
명령으로 획득할 수 있고, MySQL에서 제공하는 잠금 가운데 가장 범위가 크다글로벌 락
을 획득하면 다른 세션에서 SELECT
를 제외한 대부분의 DDL/DML 문장을 실행하는 경우 글로벌 락이 해제될 때까지 해당 문장이 대기 상태
로 남는다글로벌 락
이 영향을 미치는 범위는 MySQL 서버 전체
이며, 작업 대상 테이블이나 데이터베이스가 다르더라도 동일하게 영향을 미친다글로벌 락
을 사용해야 한다InnoDB 스토리지 엔진
은 트랜잭션을 지원하기 때문에 일관된 데이터 상태를 위해 모든 데이터 변경 작업을 멈출 필요는 없다MySQL 8.0
부터 InnoDB가 기본 스토리지 엔진으로 채택되면서 조금 더 가벼운 글로벌 락의 필요성이 생겼고, 백업 툴들의 안정적 실행을 위한 백업 락
이 도입됐다REPAIR TABLE
과 OPTIMIZE TABLE
명령FLUSH TABLES WITH READ LOCK
명령을 이용해 글로벌 락을 획득하면 복제는 백업 시간만큼 지연될 수 밖에 없다정상적으로 복제는 실행되지만 백업의 실패를 막기 위해 DDL 명령이 실행되면 복제를 일시 중지 하는 역할
을 한다LOCK TABLES table_name [ READ | WRITE ]
UNLOCK TABLES
명령으로 잠금을 반납(해제)할 수 있음온라인 작업에 상당한 영향
을 미치기 때문이다변경하는 쿼리를 실행
하면 발생한다즉시 잠금을 해제
하는 형태로 사용된다자동으로 획득
됐다가 쿼리가 완료되면 자동 해제
된다InnoDB
의 경우 스토리지 엔진 차원에서 레코드 기반 잠금
을 제공해서, 단순 데이터 변경 쿼리로 인해 묵시적 테이블 락
이 설정되지는 않는다데이터 변경(DML)
쿼리에서는 무시되고, 스키마를 변경하는 쿼리(DDL)
의 경우에만 영향을 미친다GET_LOCK
함수를 통해 임의의 문자열에 대해 잠금을 설정할 수 있다AUTO_INCREMENT
와 같은 데이터베이스 객체가 아니라는 것이다문자열
에 대해 획득하고 반납(해제)하는 잠금이다여러 클라이언트가 상호 동기화
를 처리해야할 때 네임드 락
을 이용하면 쉽게 해결할 수 있다많은 레코드를 변경
하는 쿼리는 자주 데드락
의 원인이 되곤 한다동일 데이터를 변경하거나 참조
하는 프로그램끼리 분류해, 네임드 락
을 걸고 쿼리를 실행하면 아주 간단히 해결할 수 있다RENAME TABLE tab_a TO tab_b
같이 테이블의 이름을 변경하는 경우 자동으로 획득하는 잠금RENAME
작업을 나눠서 실행하면 아주 짧은 순간이지만, RENAME하려는 테이블이 존재하지 않는 순간이 발생해 오류를 뱉는다InnoDB 스토리지 엔진
은 MySQL에서 제공하는 잠금과는 별개로 스토리지 엔진 내부에서 레코드 기반의 잠금 방식을 탑재하고 있다레코드 기반
잠금 방식 덕분에 훨씬 뛰어난 동시성 처리
를 제공할 수 있다이원화된 잠금
처리 탓에 사용되는 잠금에 대한 정보는 MySQL 명령을 이용해 접근하기가 상당히 까다롭다INN_DB_TRX, INNODB_LOCKS, INNODB_LOCK_WAITS
레코드
기반의 잠금 기능을 제공락 에스컬레이션
)은 없다갭(GAP)
락이라는 것이 존재한다레코드 락
이라 한다인덱스의 레코드
를 잠근다자동 생성된 클러스터 인덱스
를 이용해 잠금을 설정한다레코드 사이의 간격
만을 잠금생성(INSERT)
되는 것을 제어하는 역할넥스트 키 락
의 일부로 자주 사용됨REPEATABLE READ
격리 수준을 사용해야 함innodb_locks_unsafe_for_binlog
시스템 변수가 비활성화되면 변경을 위해 검색하는 레코드에는 넥스트 키 락
방식으로 잠금이 걸린다InnoDB
의 갭 락
이나 넥스트 키 락
은 바이너리 로그에 기록되는 쿼리가 레플리카 서버
에서 실행될 때, 소스 서버
에서 만들어 낸 결과와 동일한 결과
를 만들어내도록 보장하는 것이 주목적데드락
이 발생하거나, 다른 트랜잭션을 기다리게 하는 일이 자주 발생한다바이너리 로그 포맷
을 ROW
형태로 바꿔서 넥스트 키 락이나 갭 락을 줄이는 것이 좋다AUTO_INCREMENT
라는 칼럼 속성을 제공한다동시
에 여러 레코드가 INSERT
되는 경우, 저장되는 각 레코드는 중복되지 않고
, 저장된 순서대로 증가
하는 일련번호 값을 가져야 한다AUTO_INCREMENT 락
이라고 하는 테이블 수준의 잠금을 사용한다INSERT
나 REPLACE
문장에서 AUTO_INCREMENT
값을 가져오는 순간만 락이 걸렸다가 즉시 해제된다AUTO_INCREMENT
락은 테이블에 단 하나만 존재하기 때문에, 두 개의 INSERT
쿼리가 동시에 실행되는 경우 하나의 쿼리가 AUTO_INCREMENT
락을 걸면 나머지 쿼리는 AUTO_INCREMENT
락을 기다려야한다AUTO_INCREMENT
칼럼에 명시적으로 값을 설정해도 자동 증가 락을 걸게 된다INSERT
가 수행되면, InnoDB 스토리지 엔진은 여러 개의 자동 증가 값을 한 번에 할당받아서 INSERT되는 레코드에 사용한다