이상 현상
트랜잭션 격리 수준(Isolation Level)과 그로 인해 발생하는 부정합 문제는 아래와 같다.
팬텀리드(phantom reads)
•
한 트랜잭션 내에서 동일한 쿼리를 2번 이상 보냈을 때 해당 조회 결과가 다른 것을 의미합니다.
◦
사이즈(size)가 하나 더 발생한 모습입니다.
◦
즉, 없던 데이터가 생김
◦
다른 행이 더 추가가 된 모습입니다.
•
유령(phantom) 같이 생겨버렸다고 해서 팬텀리드
•
팬텀 리드의 확장성
◦
위와 같이 동일 쿼리가 아니더라도 의미상 같은 쿼리를 날렸을 때, 데이터 불일치가 발생
▪
위에서는 t2가 새로 생김
▪
이로 인해 t1의 첫번째 v>10(cnt)과 두번째 cnt의 결과가 달라짐
반복 가능하지 않은 조회(Nonrepeatable Reads)
•
같은 데이터의 값이 달라짐
•
Fuzzy read라고도 부른다
•
한 트랜잭션 내의 같은 행에 두 번 이상조회가 발생했는데, 그 값이 다른 것을 말합니다.
◦
반복 가능하지 않은 조회가 더 작은 개념 ⇒ 행에 국한된 개념
더티 리드(Dirty Reads)
하나의 트랜잭션이 다른 트랜잭션의 아직 커밋되지 않은 데이터를 읽는 현상입니다.
•
T(쓰레드)1 이 업데이트 이후 롤백을 하여 커밋되지 않은 데이터가 됬음에도 불구하고 T2는 이미 커밋이 되었다 라고 판단하게 됩니다.
위의 현상들을 모두 발생하지 않게 만들 수는 있지만, 그렇게 될 경우, 제약 사항들이 많아져서 동시 처리 가능한 트랜잭션 수가 줄어들어 결국 DB의 전체 처리량이 하락하게 된다
일부 이상한 현상은 허용하는 몇가지 레벨을 만들어서 사용자가 필요에 따라서 적절하게 선택할 수 있도록 하자
트랜잭션의 격리 수준(Isolation Level)
트랜잭션의 격리 수준(Isolation Level)이란
•
여러 트랜잭션이 동시에 처리될 때, 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있게 허용할지 여부를 결정하는 것.
•
트랜잭션의 격리 수준은 격리(고립) 수준이 높은 순서대로 SERIALIZABLE, REPEATABLE READ, READ COMMITTED, READ UNCOMMITED가 존재한다.
◦
SERIALIZABLE (가장 높음)
◦
REPEATABLE READ
◦
READ COMMITTED
◦
READ UNCOMMITED (가장 낮음)
•
격리 수준에 따른 현상들
•
Serializable
◦
위 세가지 현상 뿐만 아니라 이상한 현상 그 자체가 발생하지 않는 고립성 완전의 레벨
•
어플리케이션 설계자는 isolation level을 통해 전체 처리량과 데이터 일관성 사이에서 어느정도 트레이드 오프를 할 수 있다.
추가적인 이상 현상
Dirty Write
•
한 트랜잭션이 아직 커밋되지 않은 다른 트랜잭션에 의해 변경된 데이터를 덮어쓸 때 발생하는 문제
◦
commit 안된 데이터를 write 한다
•
이 경우, 한 트랜잭션이 데이터를 변경했지만 아직 확정(commit)하지 않았는데, 다른 트랜잭션이 동일한 데이터를 덮어쓰게 된다.
•
만약 첫 번째 트랜잭션이 나중에 롤백될 경우, 두 번째 트랜잭션에 의한 변경은 첫 번째 트랜잭션이 존재하지 않았던 것처럼 보이게 된다.
◦
초기 x=0
◦
abort 시 x=100으로 바뀐 것이 rollback 되어버림
•
rollback 시 정상적인 recovery는 매우 중요하기 때문에 모든 isolation level에서 dirty write를 허용하면 안된다.
•
예방
◦
데이터에 대한 쓰기 잠금(write lock)을 구현하여 한 번에 한 트랜잭션만 데이터를 변경할 수 있도록 한다
Lost update
•
update가 되었는데 반영이 되지 않은 사항
•
두 개 이상의 트랜잭션이 거의 동시에 동일한 데이터를 읽고, 이 데이터를 기반으로 변경을 수행할 때 발생
•
두 트랜잭션이 동일한 데이터를 독립적으로 변경하고, 한 트랜잭션에 의한 변경이 다른 트랜잭션에 의해 덮어쓰여질 때 발생하여, 한 트랜잭션의 업데이트가 손실된다.
◦
초기 값 x=50
◦
결과 값 x=100
◦
중간 업데이트 사라짐
Read Skew (또는 Non-Repeatable Read)
•
inconsistent read
•
Read skew는 트랜잭션이 실행되는 동안 같은 데이터를 두 번 이상 읽을 때, 두 번째 (또는 그 이후) 읽기 동작에서 첫 번째 읽기 동작과 다른 값을 반환할 수 있는 현상.
•
이는 다른 트랜잭션이 첫 번째 읽기와 두 번째 읽기 사이에 값을 업데이트하고 커밋할 때 발생
•
이로 인해 데이터베이스에서 일관성 없는 또는 잘못된 결정이 이루어짐.
◦
예를 들어, 트랜잭션이 한 번에 한 항목만 읽고, 그 값에 기반하여 결정을 내릴 때, 다른 트랜잭션이 동일한 항목을 변경할 수 있음
◦
초기 x = 50, y = 50
◦
트랜잭션 1번 같은 경우는 x=10, y=90 → 100
◦
트랜잭션 2번 같은 경우는 x + y = 140이 되어버림
◦
두 데이터가 값이 다름(불일치)
Write Skew
•
Inconsistent한 데이터 쓰기
•
Write skew는 두 개 이상의 트랜잭션이 거의 동시에 서로 다른 데이터 항목을 읽은 후, 이 데이터에 기반하여 쓰기 작업을 수행할 때 발생하는 문제.
◦
x = 50, y = 50
◦
위 데이터는 x+y ≥ 0 제약 조건이 있음에도 데이터를 쓰게 된다
•
이는 각 트랜잭션이 다른 트랜잭션이 수행하는 쓰기 작업을 인지하지 못하고 자신의 쓰기 작업을 수행할 때 발생
•
이 문제를 해결하기 위해 "serializable isolation" 수준을 사용
Snapshot isolation
•
트랜잭션이 자신의 작업을 수행하는 동안 데이터베이스의 "스냅샷"을 사용하여 일관된 읽기를 수행하도록 하는 격리 메커니즘
•
트랜잭션들이 데이터베이스의 이전 상태의 스냅샷을 읽고, 그들의 변경사항을 고립된 환경에서 수행하도록 하여, 동시에 여러 트랜잭션이 실행되는 환경에서 발생할 수 있는 다양한 문제들(예: dirty read, non-repeatable read, phantom read 등)을 방지하는 데 사용
•
예제
◦
초기값 x=50, y=50
◦
t1의 read(y)는 t1이 확보한 스냅샷을 기준으로 값을 읽어온다
◦
이 경우, y=50이 된다
◦
하지만 외부에서는 볼 때, y=150이 된다 (t1 시점에서만 스냅샷)
◦
스냅샷 isolation에서 같은 데이터에 한해 write - write conflict의 경우, 먼저 커밋된 트랜잭션만 인정
▪
뒤에 t1이 처리한 write를 포함한 t1의 트랜잭션 스냅샷은 abort가 되면서 폐기가 된다
•
이 스냅샷 isolation은 MVCC 중 하나의 타입이다.
•
정리하자면 트랜잭션 시작 전에 커밋된 데이터만 보이며, 첫번째 커밋 트랜잭션이 이기는 현상을 보인다