트랜잭션 격리 수준
IT 위키
- Transaction Isolation Level; 트랜잭션 격리 수준
- 동시에 실행되는 트랜잭션들이 서로에게 얼마나 영향을 주도록 허용할지를 정한 단계
격리 수준을 높이면 일관성이 좋아지는 대신 동시성(처리량)이 떨어진다. 그 사이의 맞바꿈을 고르는 것이다.
| 현상 | 내용 |
|---|---|
| 오손 읽기(Dirty Read) | 아직 커밋되지 않은 다른 트랜잭션의 변경을 읽는다. 그쪽이 롤백하면 읽은 값은 존재한 적 없는 값이 된다 |
| 반복 불가능 읽기(Non-Repeatable Read) | 같은 행을 두 번 읽었는데 사이에 다른 트랜잭션이 수정·삭제해서 값이 달라진다 |
| 팬텀 리드(Phantom Read) | 같은 조건으로 두 번 조회했는데 사이에 다른 트랜잭션이 삽입해서 없던 행이 나타난다 |
| 갱신 손실(Lost Update) | 두 트랜잭션이 같은 값을 읽고 각각 갱신해 한쪽 변경이 사라진다 |
- 반복 불가능 읽기는 "있던 행의 값이 변하는 것"이고, 팬텀 리드는 "행의 집합이 변하는 것"이다. 이 차이가 둘을 가른다.
| 격리 수준 | 오손 읽기 | 반복 불가능 읽기 | 팬텀 리드 |
|---|---|---|---|
| READ UNCOMMITTED | 발생 | 발생 | 발생 |
| READ COMMITTED | 방지 | 발생 | 발생 |
| REPEATABLE READ | 방지 | 방지 | 발생 (표준 기준) |
| SERIALIZABLE | 방지 | 방지 | 방지 |
- 기본값은 DBMS 마다 다르다. Oracle·PostgreSQL·SQL Server 는 READ COMMITTED, MySQL(InnoDB)은 REPEATABLE READ 다.
- InnoDB 는 REPEATABLE READ 에서도 넥스트 키 락(갭 락 + 레코드 락)으로 팬텀 리드를 막는다. 표준과 다른 점이다.
- Phantom Conflict
- 범위 조건으로 잠금을 건 트랜잭션과, 그 범위 안에 새 행을 삽입하려는 트랜잭션 사이의 충돌
- 이미 존재하는 행에는 락을 걸 수 있지만 아직 없는 행에는 락을 걸 수 없다. 이것이 팬텀 문제의 뿌리다
- 해결 방법
- 갭 락 / 넥스트 키 락 — 인덱스의 행 사이 간격에 락을 걸어 삽입을 막는다
- 술어 락(Predicate Lock) — 조건 자체에 락을 건다. 이론적으로 완전하지만 비용이 크다
- MVCC + 직렬화 검증 — 스냅샷으로 읽고 커밋 시점에 충돌을 검사해 실패시킨다(PostgreSQL SSI)
- 트랜잭션
- 병행 제어
