트랜잭션(Transaction)은 ACID(Atomicity, Consistency, Isolation, Durability)를 보장해야 한다.
이 중 격리성을 보장하려면 트랜잭션을 요청한 순서대로 실행해야 하는데, 병렬 처리가 불가능하므로 성능이 나빠진다. 이를 해결하기 위해 트랜잭션의 '격리 수준을 4단계'로 나누어서 트랜잭션을 최대한 동시 처리를 할 수 있도록 설계한다.
격리 수준 | DIRTY READ | NON-REPEATABLE READ | PHANTOM READ |
---|---|---|---|
커밋되지 않은 읽기(READ UNCOMMITTED) | O | O | O |
커밋된 읽기(READ COMMITTED) | O | O | |
반복 가능한 읽기(REPEATABLE READ) | O | ||
직렬화 가능(SERIALIZABLE) |
출처 : 위키피디아, Isolation(database systems)
사진은 아래 문제점들의 예시에서 사용할 데이터베이스 데이터이다.
DIRTY READ
출처 : 위키피디아, Isolation(database systems)
Transaction 2
에서 id = 1인 유저
의 나이를 21로 변경한 뒤 커밋을 하지 않았다. 이 때, Transaction 1
에서 UNCOMMITTED READ
를 하면서 수정 중인 age
값인 21을 읽은 상태이다.
이 때 Transaction 2
를 롤백하거나 다른 변경 사항(age = 22)을 업데이트하게 되면 데이터베이스의 정합성을 보장할 수 없게 된다.
이 문제가 바로 Dirty Read 이다.
NON-REPEATABLE READ
출처 : 위키피디아, Isolation(database systems)
Transaction 1
에서 id = 1인 유저
를 두 번 조회하고 Transaction 2
가 그 사이에 id = 1인 유저
의 age를 21로 바꾸었다.
이 때, Transaction 1
의 처음 조회값과 두 번째 조회값이 달라진다. 처음에는 이게 왜 문제가 되는지 이해가 안갔는데 생각해보니 한 트랜잭션 내에서 논리적으로 같은 컬럼에 대해서 다른 값을 반환하므로 데이터베이스의 일관성과 정합성에 문제를 줄 수 있어 안 좋은 것 같다는 생각이 들었다.
PHANTOM READ
출처 : 위키피디아, Isolation(database systems)
Phantom Read 는 Non-repeatable Read 의 특수한 경우다. SELECT
절 사용 시 범위 잠금(range locks) 이 획득되지 않을 경우에 발생하는데, 위의 예시처럼 Transaction 1
에서 age 가 10~30인 유저들을 처음 조회할 때는 행이 2 개(Joe, Jill) 가 반환이 되지만, Transaction 2
가 새로운 데이터를 삽입하면 두 번째 조회할 때는 행이 3 개(Joe, Jill, Bob) 이 조회된다.