by-nc-sa     개발자, DBA가 함께 만들어가는 구루비 지식창고!

트랜잭션 수준 읽기 일관성




02 트랜잭션 수준 읽기 일관성



(1) 트랜잭션 수준 읽기 일관성이란?


문장수준 읽기 일관성(Statement-Level Read Consistency)은 쿼리가 시작된 시점을 기준으로 데이터를 일관성 있게 읽어 들이는 것

트랜잭션 수준 읽기 일관성(Transaction-Level Read Consistency)은 트랜잭션이 시작된 시점을 기준으로 일관성 있게 데이터를 읽어 들이는 것

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



(2) 트랜잭션 고립화 수준


 트랜잭션 수준으로 읽기 일관성을 강화 하려면 트랜잭션 고립화 수준을 높여 주어야 한다.

트랜잭션 고립화 수준을 조절하는 방법은 네가지 수준이 있다.

ANSI / ISO SQL standard(SQL92)에서 정의함


■ 레벨 0 ( = Read Uncommitted )

 - 트랜잭션에서 처리중인 / 아직 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 것을 허용

 - Dirty Read, Non-repeatable Read, Phantom Read 현상 발생

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


■ 레벨 1 ( = Read Committed )

 - Dirty Read 방지 : 트랜잭션이 커밋되어 확정된 데이터만 읽는 것을 허용

 - 대부분의 DBMS가 기본모드로 채택하고 있는 일관성 모드

 - Non-Repeatable Read, Phantom Read 현상 발생

 - DB2, SQL Server, Sybase의 경우 읽기 공유 Lock을 이용해서 구현, 하나의 레코드를 읽을 때 Lock을 설정하고 해당 레코드에서 빠지는 순간 Lock해제

 - Oracle은 Lock을 사용하지 않고 쿼리시작 시점의 Undo 데이터를 제공하는 방식으로 구현


■ 레벨 2 ( = Repeatable Read )

 - 선행 트랜잭션이 읽은 데이터는 트랜잭션이 종료될 때까지 후행 트랜잭션이 갱신하거나 삭제하는 것을 불허함으로써 같은 데이터를 두번 쿼리했을 때 일관성 있는 결과를 리턴

 - Phantom Read 현상 발생

 - DB2, SQL Server의 경우 트랜잭션 고립화 수준을 Repeatable Read로 변경하면 읽은 데이터에 걸린 공유 Lock을 커밋할 때까지 유지하는 방식으로 구현

 - Oracle은 이 레벨을 명시적으로 지원하지 않지만 for update절을 이용해 구현 가능,

   SQL Server등에서도 for update 절을 사용할 수 있지만 커서를 명시적으로 선언할 때만 사용 가능함


■ 레벨 3 ( = Serializable Read )

 - 선행 트랜잭션이 읽은 데이터를 후행 트랜잭션이 갱신하거나 삭제하지 못할 뿐만 아니라 중간에 새로운 레코드를 삽입하는 것도 막아줌

 - 완벽한 읽기 일관성 모드를 제공

 

 트랜잭션 고립화 수준 조정기능을 위한 script

set tracsaction isolation level serializable;



낮은 단계의 트랜잭션 고립화 수준을 이용시 발생하는 현상 3가지

  • Dirty Read ( = Uncommitted Dependency )
  • Non-Repeatable Read ( = Inconsistent Analysis )
  • Phantom Read


(3) Dirty Read ( = Uncommitted Dependency)


커밋되지 않은 수정 중인 데이터를 다른 트랜잭션에서 읽을 수 있도록 허용할때 발생

대부분 DBMS가 기본 트랜잭션 고립화 수준을 레벨1 로 설정하고 있어 Dirty Read는 발생하지 않음

 =  커밋된 데이터만 읽을 수 있도록 허용

SQL Server, Sybase등은 데이터를 읽을 때 공유 Lock을 사용,

갱신중인 레코드에는 배타적 Lock이 걸림, 이는 공유 Lock과는 호환되지 않아 갱신중인 레코드는 읽지 못함(Lock에 의한 동시성 저하 발생)

오라클은 다중 버전 읽기 일관성 모델을 채택함으로써 Lock을 사용하지 않고도 Dirty Read를 피해 일관성 있는 데이터 읽기가 가능

 

(4) Non-Repeatable Read ( = Inconsistent Analysis)


 한 트랜잭션 내에서 같은 쿼리를 두번 수행 할 때 그 사이에 다른 트랜잭션이 값을 수정 또는 삭제함으로써

두 쿼리의 결과가 상이하게 나타나는 비일관성이 발생하는 것을 말함


(5) Phantom Read


한 트랜잭션 안에서 일정 범위의 레코드를 두번 이상 읽을 때, 첫번째 쿼리에서 없던 레코드가 두번째 쿼리에서 나타나는 현상

이는 트랜잭션 도중 새로운 레코드가 삽입되는 것을 허용하기 때문에 나타나는 현상임.

Phantom Read현상을 방지하려면 트랜잭션 고립화 수준을 레벨3으로 올려 주어야 한다.

고립화 수준을 높이면 데이터 일관성은 확보 되지만 동시성이 현격히 저하되는 결과를 초래함

오라클은 해당 쿼리의 SCN 확인 과정을 통해 질의 시점에 존재했던 데이터만을 대상으로 집계 수행을 하므로 동시성을 저하시키지 않으면서 일관성을 유지

트랜잭션 고립화 수준을 높이면 일관성은 향상 되지만 더 넓은 범위의 Lock을 더 오랫동안 유지하는 방식으로 동시성을 저하한다.(그림2-2참조)

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


 

참조


 

위 사용된 Image는 마소7월호에서 발췌하였습니다.

문서정보

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. 10월 29, 2009

    강정식 says:

    이번주 스터디는 참석 못하지만 비투엔 Q&A에서 이번주에 다룰 Phantom Read에 대해 질문 올라온게 있어서 리플 달아드립니다. ...

    이번주 스터디는 참석 못하지만 비투엔 Q&A에서 이번주에 다룰 Phantom Read에 대해 질문 올라온게 있어서 리플 달아드립니다.

    http://www.b2en.com/question/question_01_01.aspx?num=864&page=2

    I. Phantom Read 질문(p111)
    안녕하세요 김균도 입니다.

    선생님이 보여주신
    p111 하단 예제를 테스트 시

    선생님께서는..p112 중반에 언급했듯이
    ~
    " 반면, 오라클은 Lock을 전혀 사용하지 않은 상태에서 1번과 2번쿼리 모두
    SCN확인 과정을 통해 t1시점에 존재했던 고객만을 대상으로 집계를 수행하므로
    동시성을 저하시키지 않으면서 일관성을 유지한다"

    라고 하셨는데..

    제가 테스트 해본결과 tx2에서 insert후 commit한 것이
    마지막 "연령대별고객" 테이블에 포함이 되어져 나옵니다.

    그리고..p112의 예제에서도..
    역시 p113 상단 글에서
    ~
    "오라클은 TX1 트랜잭션이 t4시점에 delete문장을 수행하더라도
    t1시점에 존재했던 레코드만 찾아서 지우기 때문에 Lock을 사용하지 않고도
    TX2 트랜잭션에 의해 추가된 로그 데이터는 안전하게 보호한다"
    라고 하셨는데.

    제가 테스트한 결과 TX1에서 마직막으로 Delete를 하면 전부 delete되어 버립니다.

    말씀하신 내용과 좀 차이가 있었 질문을 드립니다.

    답변 부탁드립니다..

    II. 답변 드립니다.
    1. 직접 테스트해 보니 tx2에서 insert후 commit한 것이 마지막 '연령대별고객' 테이블에 포함이 되어져
    나온다고 하셨는데, Phantom Read는 바로 그런 현상을 말하는 것입니다. 한 트랜잭션 내에서 같은 쿼리를
    두 번 수행했는데, 다른 트랜잭션이 발생시킨 변경사항 때문에 두 쿼리의 수행결과가 다른 것을 말하죠.
    이런 현상을 방지하려면 isolation level을 serializable로 올려주어야 한다고 112페이지에 설명하고
    있습니다.

    2. 직접 테스트해 보니 TX1에서 마직막으로 Delete를 하면 전부 delete되어 버린다고 하셨는데, 이것
    역시도 Phandom Read 현상에 의한 것이죠. TX1 트랜잭션은 t1 시점에 백업한 데이터만 지우려고 한 것인데,
    중간에 TX2에 의해서 입력된 데이터까지 지워져 버렸으니까요.

    1번, 2번 모두 김균도님께서 테스트한 내용이 맞구요, 제 책에도 isolation level이 낮을 때 바로 그런
    현상이 발생할 수 있음을 설명한 것입니다.

    답변이 되셨는지요?
    좋은 하루 되십시오.

    III. 답변감사드립니다. 하지만..
    답변 감사드립니다..
    하지만 선생님께서 쓰신 책내용에는...

    Oracle이 굳이 isolation level을 serializable 하게 설정하지 않아도
    Phantom Read 현상이 나타나지 않는다는걸로 해석할수 있습니다.

    앞서 언급했지만..
    p112 중간 쯤에..

    ---------------------------------------------------
    ..반면, 오라클은 Lock을 전혀 사용하지 않은 상태에서 1번과 2번쿼리 모두
    SCN확인 과정을 통해 t1시점에 존재했던 고객만을 대상으로 집계를 수행하므로
    동시성을 저하시키지 않으면서 일관성을 유지한다..;
    -------------------------------------------------------

    그리고 p113 위에서 4번째 줄을 보시면.
    ---------------------------------------------------------
    ...오라클은 TX1 트랜잭션이 t4시점에 delete문장을 수행하더라도
    t1시점에 존재했던 레코드만 찾아서 지우기 때문에 Lock을 사용하지 않고도
    TX2 트랜잭션에 의해 추가된 로그 데이터는 안전하게 보호한다...
    ---------------------------------------------------------

    음..저만..그렇게 생각을 하는지....
    아무튼 선생님의 의도는 Oracle의 기본 isolation level에서는 Phantom Read현상이 발생 한다는것이지요..

    감사합니다..

    IV. 다시 답변 드립니다.
    말씀하신 112 페이지 중간 문단을 보시면...
    ---------------------------------------------------------------------------------------------------
    고립화 수준을 레벨 3으로 높이면
    SQL Server에서는 ~ Lock을 통해 ~ 데이터 일관성은 확보되지만 동시성이 현격이 저하 ~~ 초래한다. 반면,
    오라클은 Lock을 전혀 사용하지 않은 상태에서 ~~ 동시성을 저하시키지 않으면서 일관성을 유지한다.
    ---------------------------------------------------------------------------------------------------
    고립화 수준을 레벨 3, 즉 serializable로 높인 경우 SQL Server와 오라클의 차이점을 설명하는 것입니다.

    113 페이지 문단도 마찬가지입니다.
    ---------------------------------------------------------------------------------------------------
    고립화 수준을 레벨 3으로 올려주면 이를 방지할 수 있다. 그러면
    SQL Server에서는 ~
    오라클은 ~
    ---------------------------------------------------------------------------------------------------
    '고립화 수준을 레벨 3으로 올려주면'이라는 단서를 붙이고 나서 SQL Server와 오라클의 차이점을 설명하고
    있습니다.

    좋은 질문에 감사드립니다.

    조시형 드림

  2. 10월 29, 2009

    꼬챙이 says:

    아마도 질문이는 오라클은 전부 지원을 한다고 생각을 하고 질문을 했던 모양인데 오라클은 Default가 1 이라고 합니다. 그러니 당연히 레벨...

    아마도 질문이는 오라클은 전부 지원을 한다고 생각을 하고 질문을 했던 모양인데 오라클은 Default가 1 이라고 합니다.

    그러니 당연히 레벨 조정을 하지 않고 수행을 하면 Phantom Read가 발생을 하게 되겠지요.

    조시형씨의 서술에 보면 Phantom Read가 발생을 하니

    "Phantom Read현상을 방지하려면 트랜잭션 고립화 수준을 레벨3으로 올려 주어야 한다." 라고 책에 기술되어 있는데,

    낮은 단계의 트랜잭션 고립화 수준을 이용시 발생하는 현상 3가지에 Phantom Read가 있고 이 현상이 발생을 할때  방지를 해야하니

    레벨을 올려 주는 방법을 사용하는 것입니다.

    << 오라클은 default가 1이라고 TeLI2 오라방이 그랬음.>>