데이터베이스

[MySQL] 잠금의 종류와 기능

후뿡이 2024. 5. 2. 22:42

Real MySQL 8.0 <교보문고>

 

• 본 글은 도서 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 스토리지 엔진은 몇 가지 특징이 있다.

  1. 다른 스토리지 엔진과 다르게 트랜잭션 기능을 제공한다.
  2. 레코드 단위의 락을 제공한다.
  3. 트랜잭션 잠금, 잠금 대기 중인 트랜잭션 모니터링 기능을 제공한다.

 

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 값이 복구되지 않는다. ) 
  • 한 번 증가하면 줄지 않는다. (잠금을 최소화하기 위함)