12-23-transaction-lock¶
Real MySQL 8.0 - 05. 트랜잭션과 잠금
last updated: 2025.12.30
트랜잭션: 완전성을 보장
- 작업의 일부만 적용되는 현상이 발생하지 않도록 하는 기능
- 정합성을 보장하기 위한 기능
잠금: 동시성을 제어하기 위한 기능
- 여러 커넥션에서 동시에 동일한 자원을 요청할 경우 순서대로 처리
격리 수준: 트랜잭션의 작업 내용을 어떻게 공유하고 차단할지 결정하는 레벨
트랜잭션¶
- DB 커넥션을 가지고 있는 범위와 트랜잭션이 활성화된 프로그램의 범위를 최소화
- 네트워크 작업이 있는 경우 트랜잭션에서 배제하기 -> DB가 높은 부하/위험한 상태
엔진 잠금¶
- 스토리지 엔진 레벨 - 스토리지 엔진 간 상호 영향x
- 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¶
- 단순하면서 가장 엄격한 격리 수준 -> 동시 처리 능력 떨어짐
- 읽기 잠금 - 다른 트랜잭션 변경 불가