행위

CONSISTENT READ

DB CAFE

Dbcafe (토론 | 기여)님의 2024년 3월 25일 (월) 23:53 판 (실제로 오라클이 CR 블록을 어떻게 관리하는지 테스트)
(차이) ← 이전 판 | 최신판 (차이) | 다음 판 → (차이)
thumb_up 추천메뉴 바로가기


1 Oracle CR 읽기 (Consistent Read)[편집]

  • Consistent Read(일관된 읽기)의 약자
  • 블록 읽기 작업시 기본적으로 CR을 수행한다.
  • Query가 시작하는 시점의 SCN과 호환되는 일관된 버전의 데이터, 즉 과거 버전의 데이터를 읽는다는 것을 의미한다.

Cr read1 ukja.gif


  • 그림 설명
  1. 세션 A가 블록 X의 특정 로우를 변경하면 블록 X는 Dirty 블록이 된다.
  2. 세션 B가 Dirty 블록 X를 읽을려고 하면 오라클은 블록 X의 과거 버전인 CR 블록을 만들고 롤백을 수행한다.
    - 즉, Dirty상태로 되기 전의 데이터를 적용해서 과거 버전의 데이터를 만든다. (이 과정을 CR 카피라고 부른다)
  3. 세션 B는 이 CR 블록을 읽어 들인다.

1.1 X$BH 뷰[편집]

  1. 오라클에서 블록의 상태를 보는 가장 좋은 방법은 Fixed View 중 하나인 X$BH 뷰를 보는 것
  2. CR 작업의 정체를 파악하려면 다음과 같은 컬럼들의 의미를 알아야 함.
    - DBARFIL : 데이터파일 번호
    - DBABLK : 블록 번호
    - STATE : 블록 상태. 3 인 경우가 CR이다. 0 = Free, 1 또는 2 가 Current 상태의 블록이다(즉 CR의 반대)
    - OBJ : 오브젝트 번호. dba_all_objects.data_object_id 또는 object_id와 조인된다.
    - CR_SCN_BAS, CR_SCN_WRP : CR 블록인 경우 SCN 정보
    - CR_UBA_FIL, CR_UBA_BLK : CR 블록인 경우 롤백에 사용된 언두 정보
-- xbh.sql
select obj, dbarfil, dbablk, state
     , cr_scn_bas, cr_scn_wrp, cr_uba_fil, cr_uba_blk
  from sys.xm$bh 
 where obj in (오브젝트 번호...)
 order by obj
;

1.2 실제로 오라클이 CR 블록을 어떻게 관리하는지 테스트[편집]

1) cr_test 테이블 만들고 1건 Insert

CREATE TABLE cr_test(id INT PRIMARY KEY, name VARCHAR2(10));
INSERT INTO index_test VALUES(1, 'name1');
COMMIT;

SELECT data_object_id FROM all_objects 
 WHERE object_name = 'CR_TEST';
==> 59262, 즉 오브젝트 아이디 = 59262

SELECT dbms_rowid.rowid_relative_fno(rowid), dbms_rowid.rowid_block_number(rowid) 
  FROM cr_test;
==> 4, 319 즉 파일 번호 = 4, 블록 번호 = 319

2) 우선 버퍼 캐시를 Flush

ALTER SYSTEM FLUSH BUFFER_CACHE;

3) 이 상태에서 세 개의 세션 Session A, B, C 에서 다음과 작업을 수행하면 xbh.sql 스크립트를 이용해 4/319 블록의 상태 확인

Session A: SELECT * FROM cr_test;

Session C: @xbh

Cr result1 ukja.gif


4) 4/319 블록이 1번(Current) 상태로 존재함을 알 수 있다. 아직 Dirty 상태가 아니기 때문.

5) Update를 수행해서 Dirty 블록을 만든다.

Session A: UPDATE cr_test SET name = 'name2';

Session C : @xbh

Cr result2 ukja.gif

--> 4/319 블록에 대해 CR 블록(State=3)이 생겼음을 알 수 있다. 즉 Update에 의해 Dirty 블록을 만들어지는 시점에 오라클은 하나의 CR 카피본을 만든다.


6) 이제 Session B에서 Dirty 블록에 대해 읽기를 수행한다.

Session B : select * from cr_test;

Cr result3 ukja.gif


--> CR 블록이 하나 더 생겼음을 알 수 있다(맨위). 이 CR 블록은 기존의 CR블록(SCN_BAS가 399558603인)의 카피본이며 실제 롤백시 수행되었음(CR_UBA_FIL = 2)을 알 수 있다.


7) Session B 에서 십여 차례 select * from cr_test 쿼리를 수행한다.

Cr result4 ukja.gif

--> CR 블록이 최대 5개까지만 만들어지는 것을 확인할 수 있다. Select 요청이 있을 때마다 가장 가까운 CR 블록을 이용해 새로운 CR 카피본을 만들고 필요한 경우 롤백을 수행한다. 5개를 초과하면 가장 오래된 CR 블록은 밀려난다. 이 값은 _DB_BLOCK_MAX_CR_DBA 파마리터에 의해 결정된다.


8) 아래 결과는 Session B에서 계속해서 Select를 수행한 결과인데 CR_SCN_BAS가 최근 값을 모두 바뀐 것을 확인할 수 있다.

Cr result5 ukja.gif


오라클이 CR 블록을 유지하는 방식은 아래와 같이 설명할 수 있다.

Time Session1 Session2
T0
T1 Update (Dirty block)
T2 Select CR 1(T2) 생성
T3 Select CR 2(T3) 생성
T4 Select CR 3(T4) 생성
T5 Select CR 4(T5) 생성
T6 Select CR 6(T6) 생성
T7 Select CR 7(T7) 생성 --> CR1 제거
T8 Select CR 8(T8) 생성 --> CR2 제거
  • 질문

1) 왜 오라클은 최근 5개의 CR 블록을 계속 갱신하면서 유지하는가?

  1. 이에 대한 대답은 CR 작업을 좀 더 효율적으로 하기 위해서이다. 즉, 최대 5개까지 가장 최근의 CR 블록을 유지함으로써 과거 버전 읽기 작업에 드는 부하를 최소화하기 위함이다.
  2. 오라클은 Select 요청에 맞는 CR 블록을 생성하기 위해 CR 카피를 만들고, Undo로부터 롤백을 수행하는 일련의 작업을 수행하는데, 이 작업의 부하를 최소화하기 위해 버퍼 캐시에 최근의 CR 블록을 여러 개 유지하는 것이다.


2) 하나의 블록당 여러 개의 CR 블록을 유지함으로써 메모리의 낭비를 유발하지 않는가?

  1. 실제로 그렇다. 오라클의 특정 버전에서는 CR 블록 수가 너무 많아져서 버퍼 캐시의 효율성이 떨어지는 현상이 실제로 있었다.
  2. 하지만 최신 버전의 오라클은 CR 블록의 위치를 LRU 리스트의 꼬리쪽으로 위치시킴으로써 메모리 부족 현상이 생길때 되도록 빨리 밀려나도록 해준다.
  • 오라클의 CR 블록과 Consistent Read는 다른 DB에서는 잘 지원하지 못하는 MVRC(Multi Versioning Read Consistency)를 가능하게 하는 핵심 메커니즘이다.
  • 여러분은 오라클을 잘 알고 있다고 생각하는가!!! 그렇다면 여기서 제시한 CR 작업에 대한 이해를 여러분의 지식 주머니안에 넣고 다녀야 할 것이다. ^^
  • 더불어 아래에 필자가 저술한 책을 한번씩 읽어 보길 권한다. 책 광고 아니냐고? 책 광고 맞다. 하지만 읽게 되면 여러분의 내공이 아마 한 갑자 정도는 늘어날 것이다...

출처) https://blog.naver.com/PostView.naver?blogId=ukja&logNo=120040625665&parentCategoryNo=&categoryNo=3&viewDate=&isShowPopularPosts=false&from=postList