IT

[Oracle] 오라클 트랜잭션 수준 읽기 일관성, Transaction-Level Read Consistency

정미나 2018. 4. 30. 15:50

트랜잭션 수준 읽기 일관성


앞서 알아보았던 문장수준 읽기 일관성이 쿼리 시작 시점을 기준으로 삼았다면 트랜잭션 수준 읽기 일관성은 트랜잭션이 시작된 시점을 기준으로 일관성 있게 데이터를 읽어들이는 것을 말한다.


[Oracle] 문장수준 읽기 일관성 자세히보기


※ 오라클은 완벽한 문장수준의 읽기 일관성을 보장하지만, 트랜잭션에 대해서는 기본적으로 보장하지 않는다.


트랜잭션 고립화 수준 (Transaction Isolation Level)

- Level 0 (Read Uncommitted): Dirty Read, Non-Repeatable Read, Phantom Read 발생

* 오라클은 이 레벨을 지원하지 않음

- Level 1 (Read Committed): 거의 모든 DBMS의 Default, Non-Repeatable Read, Phantom Read 발생

- Level 2 (Repeatable Read): 선행 트랜잭션이 읽은 데이터는 트랜잭션이 종료될 때까지 후행 트랜잭션이 갱신 및 삭제 불가, Phantom Read 발생, Oracle의 for update

- Level 3 (Serializable Read): 선행 트랜잭션이 읽은 데이터는 트랜잭션이 종료될 때까지 후행 트랜잭션이 갱신, 삭제, 삽입 불가, 완벽한 읽기 일관성 모드를 제공


dirty read.. 더러운 것을 읽는다? 

non-repeatable read.. 반복될 리 없는 것을 읽는다? 

phantom read.. 유령을 읽는다???


(1) Dirty Read (= Uncommitted Dependency)

: 커밋되지 않은 데이터를 읽음으로써 발생하는 현상

 TX1

 

 TX2

 

t1

 UPDATE 계좌 SET 잔고 = 잔고 + 10000

  WHERE 계좌번호 = '123456';

 SELECT SUM(잔고) FROM 계좌;

t2


 

t3

 ROLLBACK;

 TX1의 최종 결과값이 비일관성 상태에 놓이게 됨


(2) Non-Repeatable Read (= Inconsistent Analysis) : SELECT 중에 UPDATE나 DELETE를 허용함으로써 발생하는 현상

 TX1

 

 TX2

 SELECT 당월주문금액 into :amt

   FROM 고객

  WHERE 고객번호 = 123;

t1

 

 

t2

 UPDATE 고객 

    SET 당월주문금액 = 60000, 등급 = 'A'

  WHERE 고객번호 = 123;

 

t3

 COMMIT;

 IF :amt >= 50000 THEN

    UPDATE 고객

       SET 등급 = 'A'

     WHERE 고객번호 = 123;

 ELSE

    UPDATE 고객

       SET 등급 = 'B'

     WHERE 고객번호 = 123;

 END IF;

t4

 


 COMMIT;

t5

 

 t1 시점에 123번 고객의 당월주문금액이 40,000원이었다고 가정하면 최종적으로 당월주문금액 = 60,000 / 등급 = 'B'가 되는 Lost Update 발생 (SELECT .. FOR UPDATE를 통해 방지 가능)


(3) Phandom Read

: SELECT 중에 INSERT를 허용함으로써 발생하는 현상

 TX1

 

 TX2

 INSERT INTO 지역별고객

 SELECT 지역, COUNT(*)

   FROM 고객

  GROUP BY 지역;

t1

 

 

t2

 INSERT INFO 고객 

 (고객번호, 이름, 지역, 연령대, ...)

 VALUES (:a, :b, :c, :d, ...);

 

t3

 COMMIT;

 INSERT INTO 연령대별고객

 SELECT 연령대, COUNT(*)

   FROM 고객

  GROUP BY 연령대;

t4

 


 COMMIT;

t5

 

 지역별고객과 연령대별고객의 총고객수가 일치하지 않는 현상 발생 (트랜잭션 고립화 수준을 레벨3로 올림으로써 방지 가능)

set transaction isolation level serializable;

TX1의 모든 쿼리를 t1시점(트랜잭션 시작 시점)에 존재했던 고객만을 대상으로 수행


※ 오라클은 트랜잭션 고립화 수준을 높이더라도 Lock을 사용하지 않으므로 동시성이 저하되지는 않는다.

(오라클은 for update절을 사용하지 않는 한 절대 select문에 Lock을 사용하지 않는다.)


문장 수준(쿼리 단위)과 트랜잭션 수준(트랜잭션 단위)을 혼동하지 말자!!