콘텐츠로 이동

12-23-transaction-lock

Real MySQL 8.0 - 05. 트랜잭션과 잠금

last updated: 2025.12.30


트랜잭션: 완전성을 보장

  • 작업의 일부만 적용되는 현상이 발생하지 않도록 하는 기능
  • 정합성을 보장하기 위한 기능

잠금: 동시성을 제어하기 위한 기능

  • 여러 커넥션에서 동시에 동일한 자원을 요청할 경우 순서대로 처리

격리 수준: 트랜잭션의 작업 내용을 어떻게 공유하고 차단할지 결정하는 레벨


트랜잭션

  • DB 커넥션을 가지고 있는 범위와 트랜잭션이 활성화된 프로그램의 범위를 최소화
  • 네트워크 작업이 있는 경우 트랜잭션에서 배제하기 -> DB가 높은 부하/위험한 상태

엔진 잠금

  1. 스토리지 엔진 레벨 - 스토리지 엔진 간 상호 영향x
  2. MySQL 엔진 레벨 - 모든 스토리지 엔진에 영향
    • 테이블 락: 테이블 데이터 동기화
    • 메타데이터 락: 테이블 구조 잠금
    • 네임드 락: 사용자 정의

글로벌 락

  • SELECT를 제외한 DDL, DML 문장을 실행하는 경우 해제될 때까지 대기 상태
  • MySQL 서버 전체에 영향(모든 테이블/데이터베이스)
  • InnoDB - 백업 락
    • 데이터베이스, 테이블 들 모든 객체 생성 및 변경, 삭제
    • REPAIR TABLE과 OPTIMIZE TABLE 명령
    • 사용자 관리 및 비밀번호 변경
    • 테이블 데이터 변경은 허용
    • 레플리카 서버에서 백업 실행

테이블 락

  • 개별 테이블 단위로 설정
  • 명시적/묵시적 잠금
  • InnoDB 테이블: 레코드 기반 잠금 -> 묵시적 테이블락 설정x
    • DDL의 경우에만 영향

네임드 락

  • 임의의 문자열에 대해 잠금
  • 다중 서버에서 하나의 DB에 접근할 때 정보에 대한 상호 동기화 처리에 용이
  • 많은 레코드에 대해서 복잡한 요건으로 레코드를 변경하는 트랜잭션에 유용
  • 동일 데이터를 변경하거나 참조하는 프로그램끼리 분류해서 네임드 락을 걸고 쿼리를 실행

메타데이터 락

  • 데이터베이스 객체(테이블, 뷰 등)의 이름이나 구조를 변경하는 경우 자동으로 획득/해제

InnoDB 스토리지 엔진 잠금

  • 레코드 기반 잠금 제공
  • 레코드 사이의 간격을 잠그는 갭(GAP) 락

레코드 락

  • 레코드 자체만 잠금 - 인덱스의 레코드를 잠금
  • pk, unique index에 의한 변경 작업은 갭 락 사용x

갭 락

  • 레코드와 바로 인접한 레코드 사이의 간격만 잠금
  • 간격에 새로운 레코드가 생성되는 것을 제어
  • 넥스트 키 락의 일부로 주로 사용

넥스트 키 락

  • 레코드 락 + 갭 락
  • 같은 트랜잭션 안에서 같은 결과가 나오도록 레코드와 사이 갭을 잠금

트랜잭션 격리 수준

  • REPEATABLE READ: 한 트랜잭션 안에서는 같은 조회 결과를 보장(InnoDB의 기본 값)

  • READ UNCOMMITTED: 커밋 안된 것도 보임

  • READ COMMITTED: 커밋된 것만 보임

  • SERIALIZABLE: 완전 직렬화(느림)

자동 증가 락

  • AUTO_INCREMENT 컬럼이 사용된 테이블에 동시에 여러 레코드가 INSERT되는 경우, 동시성 처리 필요
  • AUTO_INCREMENT 락 - 테이블 수준의 잠금
  • INSERT, REPLACE 같이 새로운 레코드를 저장하는 쿼리에 필요
  • 8.0에서는 lock 모드를 설정 가능

인덱스와 잠금

  • 변경할 레코드를 찾기 위해 검색한 인덱스의 레코드 모두 잠금
  • UPDATE/DELETE WHERE 조건으로 검색을 할 때 인덱스가 있으면 해당 행만 잠금을 걸게 되는데, 만약 인덱스 컬럼이 없는 경우 테이블 전체를 스캔 하여 모든 행을 잠금

MySQL의 격리 수준(isolation level)

  • 여러 트랜잭션이 동시에 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있게 허용할지 말지 결정하는 것
DIRTY READ NON-REPEATABLE READ PHANTOM READ
READ UNCOMMITTED 발생 발생 발생
READ COMMITTED 없음 발생 발생
REPEATABLE READ 없음 없음 발생
(InnoDB는 없음)
SERIALIZABLE 없음 없음 없음
  • SERIALIZABLE 격리 수준이 아니면 성능은 비슷함
  • DIRTY READ: 어떤 트랜잭션에서 처리한 작업이 완료되지 않았는데 다른 트랜잭션에서 볼 수 있는 현상

READ UNCOMMITTED

  • COMMIT/ROLLBACK 여부와 상관없이 다른 트랜잭션에 보임
  • dirty read 허용
  • 사용하지 마라

READ COMMITTED

  • 오라클의 기본 격리 수준
  • 변경 사항 커밋 전에는 언두 영역의 백업된 레코드 조회
  • 하나의 트랜잭션에서 동일 데이터를 여러 번 읽고 변경하는 작업에서 유의

REPEATABLE READ

  • InnoDB 스토리지 엔진에서 기본으로 사용
  • 언두 영역에 백업된 이전 데이터를 이용해 동일 트랜잭션 내에서 동일한 결과 보장
  • 언두 영역에는 하나의 레코드에 대한 백업이 하나 이상 존재 가능
  • 언두 영역에는 잠금을 걸 수 없기 때문에 SELECT ... FOR UPDATE/SHARE 쿼리는 PHANTOM READ 현상 발생 가능

바이너리 로그: 데이터 변경 내용을 기록하는 로그 - 복구, 데이터 동기화에 사용

SERIALIZABLE

  • 단순하면서 가장 엄격한 격리 수준 -> 동시 처리 능력 떨어짐
  • 읽기 잠금 - 다른 트랜잭션 변경 불가