[MySQL] 잠금의 종류와 기능
• 본 글은 도서 Real MySQL 8.0을 참고해 작성한 글입니다.
🐳 잠금(Lock)이란 ?
잠금은 여러 커넥션 간의 동시성을 제어하기 위한 기능이다.
예시를 들어보자 !
유저 A와 유저 B가 동시에 데이터 X를 UPDATE 하려고 한다면 어떻게 되야 할까 ?
단계 | 유저 A | 유저 B |
1단계 | 데이터 X 업데이트를 시작함. | |
2단계 | 데이터 X에 대한 잠금을 획득함. | |
3단계 | 데이터 X를 성공적으로 업데이트. | |
4단계 | 데이터 X 업데이트를 시도함. | |
5단계 | 데이터 X에 접근 불가, 잠금 대기 중. |
유저 A가 해당 데이터 레코드 X에 대해 잠금을 획득하면 락이 해제 되기 전까지 다른 유저는 해당 데이터를 업데이트 할 수 없다.
위와 같이 같은 레코드에 대해 동시에 수정하려고 하는 경우 발생하는 동시성 문제를 제어하기 위한 기능이다.
🐳 MySQL 잠금의 종류
MySQL(MySQL 서버)은 MySQL 엔진과 스토리지 엔진으로 구성되어 있다.
MySQL의 락은 크게 두 종류가 있다.
1. MySQL 엔진 레벨의 잠금
2. 스토리지 엔진
✅ MySQL 엔진 레벨의 잠금의 종류
1. 글로벌 락
명령어 : FLUSH TABLES WITH READ LOCK
범위 : MySQL 서버 전체 - 데이터베이스가 다르더라도 동일하게 영향을 미침
사용 목적 : MyISAM,MEMORY 테이블에 대해 mysqldump로 일관된 백업을 받아야 할 때 주로 사용
큰 영향을 미치기 때문에 가급적 사용하지 않는 것이 좋음
2. 테이블 락
명령어 : LOCK TABLES table_name [READ | WRITE]
범위 : 테이블 단위
특징 1. 명시적으로 사용 가능
특징 2. 특별한 상황이 아니면 사용할 필요가 없다, 글로벌 락과 마찬가지로 온라인 작업에 상당한 영향을 미치기 때문
특징 3. 묵시적으로 사용되는 테이블 락
- MyISAM,MEMORY 테이블의 데이터를 변경하는 쿼리 실행시 발생
- InnoDB 엔진에서 DML 쿼리의 경우 대부분 무시, DDL 쿼리의 경우 테이블 락이 설정 됨
3. 네임드 락
기능 : 사용자가 지정한 문자열에 대해 잠금을 설정
용도 : 복잡한 요건으로 레코드를 변경하는 트랜잭션에 유용
락 설정 명령어 : SELECT GET_LOCK('lock_name',timeout) -> 이미 잠금 중인 경우 timeout만큼 대기하고 잠금 해제
락 확인 명령어 : SELECT IS_FREE_LOCK('lock_name') -> 락이 설정되어 있는지 확인
락 해제 명령어 : SELECT RELEASE_LOCK('lock_name') / SELECT REALEASE_ALL_LOCKS()
4. 메타데이터 락
기능 : 데이터베이스 객체( 테이블, 뷰, 저장프로시저 등 )의 이름이나 구조를 변경하는 경우에 획득하는 잠금
명시적으로 사용 불가능
DDL 쿼리 실행시 자동으로 획득
DDL 쿼리 실행 중에는 DML 쿼리가 대기
- MySQL은 한 쓰레드에서 실행되기 때문에 느림
- DDL 실행하기 보다 테이블을 여러 쿼리를 통해 여러 쓰레드에서 복제한 후 RENAME하는 것이 빠를 수 있음
✅ 스토리지 엔진(InnoDB) 레벨의 잠금
InnoDB 스토리지 엔진은 몇 가지 특징이 있다.
- 다른 스토리지 엔진과 다르게 트랜잭션 기능을 제공한다.
- 레코드 단위의 락을 제공한다.
- 트랜잭션 잠금, 잠금 대기 중인 트랜잭션 모니터링 기능을 제공한다.
InnoDB 스토리지 엔진 레벨의 잠금에는 크게 4 가지 종류가 있다.
1. 레코드 락
레코드 단위로 잠금을 설정
실제 레코드를 잠그는 것이 아니라 레코드를 조회하기 위한 인덱스를 잠근다.
보조 인덱스를 활용한 잠금은 대부분 갭락, 넥스트 키 락을 사용한다.
PK, 유니크 인덱스를 활용한 잠금은 레코드 락을 사용한다.
2. GAP 락
레코드가 아니라 레코드와 레코드의 인접한 간격을 잠그는 락
갭락 자체보다는 넥스트 키 락의 일부로 사용됨
3. 넥스트 키 락
- 앞서 설명한 레코드락과 갭락을 함께 사용하는 형태의 잠금이다.
- 격리 수준이 REPEATABLE READ 이상인 경우에 사용된다.
- InnoDB에서 Phantom Read를 방지하는 목적으로 사용된다. ( InnoDB에서도 Phantom Read가 아예 발생하지 않는 것은 아니다 ! )
- 넥스트 키 락, 갭 락 으로 인한 데드락이 발생 가능성이 높아진다.
참고 : MySQL 공식 문서
4. 자동 증가 락 (AUTO_INCREMENT LOCK)
- AUTO_INCREMENT 컬럼에 대한 락
- INSERT,REPLACE 쿼리 같이 새로운 레코드 생성 쿼리에서만 사용
- 명시적 사용 불가능
- 아주 짧은 AUTO_INCREMENT 값을 조회하는 동안에만 락이 설정되어 있음
- mode에 따라 락을 사용하거나 락보다 가벼운 래치(뮤텍스)를 사용한다. ( mode 는 0~2 까지 존재하며 클수록 성능이 좋지만 ROLLBACK 되지 않은 AUTO INCREMENT 값이 복구되지 않는다. )
- 한 번 증가하면 줄지 않는다. (잠금을 최소화하기 위함)