PE Notes · DB
팬텀 충돌과 트랜잭션 격리수준
더티 리드·반복 불가 읽기·팬텀 리드를 격리 네 수준에 대응시키고, 범위 잠금과 MVCC가 팬텀을 어떻게 다르게 막는지 정리합니다.
여러 트랜잭션이 같은 표를 건드리면, 커밋 전의 값·다시 읽은 값·새로 나타난 행이 서로를 배신합니다. SQL 표준은 그 이상 현상을 격리 네 칸에 나눠 담습니다. 는 그중 범위 조회에서만 커집니다.
이상 현상
더티 리드는 커밋 전 값을 읽습니다. 롤백되면 없는 숫자를 믿게 됩니다. 반복 불가 읽기는 같은 행을 두 번 읽었는데 값이 바뀝니다. 팬텀은 조건이 같은 SELECT의 행 수가 바뀝니다. 새 행이 유령처럼 끼어듭니다. 행 잠금만으로는 아직 없는 키를 못 막아서, 갭·범위 잠금이 필요합니다.
| 현상 | 한 줄 |
|---|---|
| Dirty Read | 남의 미커밋을 읽는다 |
| Non-Repeatable Read | 같은 행의 값이 바뀐다 |
| Phantom Read | 같은 조건의 행 집합이 바뀐다 |
| Lost Update | 한쪽 갱신이 덮인다 |
네 격리
Read Uncommitted는 셋을 다 허용합니다. Read Committed는 더티만 막습니다. Repeatable Read는 행 재읽기를 막고 팬텀은 남길 수 있습니다. Serializable은 팬텀까지 막습니다. 일관성이 올라가면 동시성은 내려갑니다.
| 수준 | Dirty | Non-Repeatable | Phantom |
|---|---|---|---|
| Read Uncommitted | 발생 | 발생 | 발생 |
| Read Committed | 방지 | 발생 | 발생 |
| Repeatable Read | 방지 | 방지 | 발생 가능 |
| Serializable | 방지 | 방지 | 방지 |
구현
InnoDB Repeatable Read는 갭 락으로 팬텀을 상당 부분 줄입니다. PostgreSQL 는 직렬화 충돌을 abort로 알립니다. 는 스냅샷으로 읽기를 막지 않으면서도, 쓰기 집합이 겹치면 팬텀을 커밋 시점에 드러냅니다.