트랜잭션 수준 읽기 일관성


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


[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을 사용하지 않는다.)


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


by 위대한 정미나 2018. 4. 30. 15:50
  • KIC 2019.12.17 22:10 ADDR EDIT/DEL REPLY

    안녕하세요? 유튜브 잘 보고 있어요!! ㅎㅎㅎㅎㅎ
    트랜잭션 수준 읽기 일관성에서 질문이 있어서 댓글남깁니당!
    오라클 성능 고도화1 교재에 보면.. 로그와 로그백업 테이블이 나오는 Phantom Read 두번째 예시가 있는데요.
    결과는 TX2가 새롭게 삽입한 데이터를 제외하고 로그 테이블에 있는 모든 데이터가 지워진다고 해요.
    그런데 제가 오라클 sqlplus로 두 세션을 띄워서 테스트한 결과 TX2가 삽입한 데이터도 함께 지워지는데 왜 그런 건지 알 수 있을까요??

  • Favicon of https://jungmina.com BlogIcon 위대한 정미나 2019.12.18 23:00 신고 ADDR EDIT/DEL REPLY

    음.. 제가 테스트 해보니 TX2가 삽입한 데이터는 지워지지 않는데.. 뭔가 착오가 있었던 건 아닐까요? ㅎㅎ 헷갈릴 수 있으니 SQLPLUS 하나 띄우시고 SQL DEVELOPER 에서 SQL창 하나 띄우시고 함 해보세용~