트랜잭션의 특성

  1. Atomicity = all or nothing : 한 트랜잭션 내의 모든 연산들이 완전히 수행되거나 전혀 수행되지 않음
  2. Consistency : 트랜잭션이 수행된 후에도 데이터베이스가 그 전과 같은 일관된 상태를 가진다.
                          "동시에 여러 사용자가 같은 데이터에 접근하려고 할 때" 발생하는 상황
  3. Isolation : 한 트랜잭션이 데이터를 갱신하는 동안 이 트랜잭션이 완료되기 전까지 다른 트랜잭션이 접근하지 못하도록 한다.
  4. Durability : 갱신한 후에 시스템이 고장나더라도 갱신된 데이터들은 쭉 지속되어야 한다.

 


Commit : 트랜잭션의 완료

Abort : 트랜잭션의 철회

= Rollback : 초기상태로 복귀

 


동시성 제어

serial schedule (직렬 스케줄) : 여러 트랜잭션들의 집합을 한번에 한 트랜잭션 씩 차례대로 수행

non-serial schedule (비직렬 스케줄) : 여러 트랜잭션들을 동시에 수행함

serializable (직렬 가능) : 비직렬 스케줄의 결과가 직렬 스케줄의 결과와 동등함, 비직렬인데 직렬이랑 똑같을 때.


동시성 제어 하지 못했을 때 문제

  • Dirty read : 커밋되지 않은 데이터 읽기 = 완료되지 않은 트랜잭션이 갱신한 데이터를 읽는 것
    한 트랜잭션에서 연산 한 다음 아직 쓰지 않았는데 다른 트랜잭션에서 읽어 와버리는 것
  • Unrepeatable read : 반복되지 않은 데이터 읽기
  • Phantom read : 가상 읽기

1. Dirty Read

"데이터 캐시에는 변경이 되었지만, 아직 디스크에는 변경되지 않은 데이터(페이지)"를 Dirty Page라고 한다.

 

 Dirty Page를 읽는 행위를 Dirty read라고 한다.

 

T1 이 롤백 돼버려서 다시 50만원으로 돌아왔는데

T2 에 의해 40만원으로 읽어버린다.

 

이 Dirty Read의 문제점은 아직 커밋되지 않은 데이터를 읽어오기 때문에,

Dirty Page를 읽어온 후에 Dirty Page의 데이터가 롤백된다면 이미 읽어온 데이터는 잘못된 데이터가 된다는 점이다.

 

 Dirty Page는 동시성이 좋아서 커밋을 기다리지 않고 값을 읽어올 수 있는 장점은 있지만,

(즉, SELECT문이 TRAN LOCK을 대기하지 않도록 하여 응답성을 높일 수 있지만)

확실히 데이터의 일관성은 떨어지게 된다.

 

이를 수행하려면 아래와 같이 격리 수준을 READ UNCOMMITTED로 설정하여야 한다.

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

 

트랜잭션이 변경한 임시 값(=Dirty Page)이 확실히 커밋될 것이라는 전제가 있을 때만 사용하여야 한다.

 

2. Unrepeatable read

반복되지 않은 읽기(Unrepeatable read)란 트랜잭션 내에서 한 번 읽은 데이터가

트랜잭션이 끝나기 전에 변경되었다면, 다시 읽었을 때 새로운 값이 읽히는 것을 의미한다.

 

T2가 끝나기 전에 T1에서 10만원을 빼버리므로 

50만원 40만원이 나온다.

 

3. Phantom read

REPEATABLE_READ 격리 수준에서는 공유 잠금인 상태의 데이터에 대해 변경 불가가 보장되었다.

하지만, 그 데이터를 변경시키지 못할 뿐 새로운 데이터를 추가/삭제하는 것은 가능하다.

이것을 팬텀 읽기(Phantom read, 가상 읽기)라고 부르는 것이다.

 

정리하면, 트랜잭션 중에 없던 행이 추가되어 새로 입력된 데이터를 읽는 것 또는

트랜잭션 중에 데이터가 삭제되어 다음 읽기시 이전에 존재하던 행이 사라지는 것 팬텀 읽기라고 한다.

 

이 팬텀 읽기를 방지하려면, 격리 수준을 SERIALIZABLE 또는 SNAPSHOT 으로 설정하면 된다.

 

1) SERIALIZABLE

 

SERIALIZABLE은 트랜잭션이 수행중일 때 INSERT/DELETE도 제한된다.

 

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

 

REPETABLE_READ가 UPDATE만 금지했던 것이 비해 INSERT/DELETE까지 제한되도록 잠금이 강화된 것이다.


 

 

격리 수준에 따라 트랜잭션이 다르게 동작한다.

 

  1. Read Uncommitted
  2. Read Committed
  3. Repeatable Read
  4. Serializable

 

격리 수준은 위에서부터 아래로 강해진다.

약하게 잠기기 때문에 데이터 접근에 대한 유연성은 좋아지지만, 데이터의 일관성은 그만큼 떨어진다 할 수 있다.


 

Read Uncommitted

 

 


Unrepeatable read

위 사용자 입장에서는 Point 1이 사라진 것처럼 보인다.

 

 

Reapeatable Read : 트랜잭션 진행되는 동안에는 데이터가 변경되더라도 같은 데이터를 읽게 해주는 방법이다.

버젼을 설정해줘서 구분한다.

 


위 사용자가 커밋이 진행되면 아래 사용자의 업데이트 커밋은 지연된다.

그리고나서 아래 사용자가 커밋을 하면 


 

명시적 잠금

select 조차 못하게 잠궈버림

아래 사용자는 잠금이 풀릴 때까지 대기한다.

커밋을 하는 시점에 잠금이 풀리게 된다.

 

Compare and Set

값이 같은지 비교해서 같은 경우에만 변경하는 것을 허용

조건을 건다. 버젼이 몇인지.


서로 다른데이터를 처리하므로 물리적으로는 경쟁 상태가 아니었다.

 

 

먼저 인덱스 기반의 잠금을 얻으면 

다른 사용자는 잠금을 얻는데에 실패하여 업데이트 쿼리를 실행할 수 없게 된다.

다른 사용자는 실패한 채로 커밋을 하거나 롤백하게 된다.

 

서로 다른 데이터를 변경하면서 발생할 수 있는 문제를 처리할 수 있다.

 

 

 

Reference

egloos.zum.com/sweeper/v/3005129

 

.

복사했습니다!