공유 락과 배타 락
| 구분 | 공유 락 (Shared Lock, Read Lock, S-Lock) | 배타 락 (Exclusive Lock, Write Lock, X-Lock) |
| 목적 | 읽기(Read) 안전 보장 -> 여러 트랜잭션이 같은 행 읽도록 함 |
쓰기(Write) 안전 보장 -> 하나의 트랜잭션만 이 행에 대해 변경 가능 |
| 다른 트랜잭션의 읽기 | 허용 | 불가 |
| 다른 트랜잭션의 쓰기 | 불가 | 불가 |
| 나와 같은 락의 동시 획득 | 가능 (S + S 가능) | 불가 (X + X 불가) |
| 쓰기 락과의 동시 획득 | S + X 불가 | X + S 불가 |
| 사용 예시 | SELECT … FOR SHARE (또는 기본 SELECT 상황 일부) |
INSERT, UPDATE, DELETE |
블로킹 (Blocking)
Lock 간의 경합이 발생하여 특정 트랜잭션이 실행되지 못하고 대기하는 상태
데드락 (Dead Lock)
두 트랜잭션이 모두 블로킹 상태가 되어, 서로의 블로킹을 해결할 수 없는 상태
격리수준 (Isolation Level) 별 S/X Lock 적용 방식
| Isolation Level | 일반 SELECT 시 락(S/X) | SELECT … FOR UPDATE / SHARE | INSERT / UPDATE / DELETE | Phantom 방지 방식 |
| READ UNCOMMITTED | ❌ 무락 (dirty read 허용) | FOR UPDATE → X락 / FOR SHARE → S락 | X락 | 없음 |
| READ COMMITTED | ❌ 무락 (스냅샷 read) | FOR UPDATE → X락 / FOR SHARE → S락 | X락 | 없음 (phantom 발생 가능) |
| REPEATABLE READ | ❌ 무락 (트랜잭션 시작 시 스냅샷 유지) | FOR UPDATE → X락 / FOR SHARE → S락 + 필요 시 갭락 | X락 + 갭락(next-key) |
없음 (phantom 발생 가능) MySQL - 갭락 |
| SERIALIZABLE | ✔ 공유락(S) 발생! | FOR UPDATE → 더 강한 X락 | X락 | S락/X락 기반으로 완전 직렬화 |
READ UNCOMMITED
- select 시 commit 되지 않은 데이터 읽음
- dirty read 발생 가능
- 실제 DB 에 존재하지 않는 데이터 읽을 수 있음
READ COMMITED
- select 시 최신 commit 데이터 읽음 (select 마다 새로운 snapshot 을 만들어 읽음)
- Non repeatable read 발생 가능
- 한 트랜잭션 내에서 같은 데이터를 두번 읽을 때, 두 데이터의 값이 다를 수 있음
- PG 는 READ COMMITED 가 default
REPEATABLE READ
- select 시 트랜잭션 시작 시점의 snapshot 을 유지하며 읽음
- Phantom Read 발생 가능
- 같은 조건으로 select 했을 때, 두 쿼리의 결과값이 달라질 수 있음
- 트랜잭션 시작 시점의 snapt shot 은 조회한 행에 대한 snapshot 이라, 새로운 행에 대해서는 해당 안됨 (행 전체 스냅샷 X)
- MySQL InnoDB 는 갭락을 통해 Phantom Read 방지
- 갭락 (gap lock, next-key lock)
- Phantom read 방지 목적을 위한 락
- 행 락 + 주변 index gap 까지 잠가서 삽입을 막는 방식
- MY SQL 은 REPEATABLE READ 가 default
SERIALIZABLE
- select 시 공유락으로 처리
MVCC
여러 버전의 데이터를 유지해서 트랜잭션이 서로 방해하지 않고 읽기/쓰기를 수행하게 하는 동시성 제어 기법
기본 아이디어:
- DB는 한 Row를 하나만 존재하게 하지 않고, 여러 버전을 유지
- 트랜잭션이 데이터를 읽을 때 자신이 시작한 시점의 버전(스냅샷)을 읽음
- 트랜잭션이 데이터를 변경할 때는 새 버전을 생성하고, 이전 버전은 UNDO나 MVCC 구조에 보존
즉, 읽기 트랜잭션과 쓰기 트랜잭션이 서로 블로킹되지 않음 → 동시성 증가
작동원리
- 트랜잭션 시작
- T1이 시작되면, T1은 현재 DB 상태의 스냅샷을 가짐
- 데이터 읽기(SELECT)
- T1은 스냅샷 기준으로 row 버전을 읽음
- 다른 트랜잭션이 UPDATE/INSERT/DELETE 하더라도 T1은 영향을 받지 않음
- 데이터 쓰기(INSERT/UPDATE/DELETE)
- T2가 UPDATE하면, 기존 row는 UNDO에 저장 → 새 row 버전을 만들어 반영
- 다른 트랜잭션은 아직 이전 버전을 계속 읽을 수 있음
- 커밋/롤백
- 커밋 시 새 버전이 공식 DB 버전으로 확정
- 롤백 시 UNDO를 사용해 이전 상태 유지
참조
https://ksh-coding.tistory.com/121
ChatGPT
'COMPUTER SCIENCE > DB' 카테고리의 다른 글
| [DB] Join (0) | 2023.02.14 |
|---|---|
| [DB] Transaction (0) | 2023.02.12 |
| [DB] Indexing (0) | 2023.02.04 |
댓글