CONSISTENT READ
DB CAFE
- DBA { Oracle DBA 명령어 > DBA 초급 과정 > DBA 고급 과정 }
- 튜닝 { 오라클 튜닝 목록 }
- 모델링 { 데이터 모델링 가이드 }
1 Oracle CR 읽기 (Consistent Read)[편집]
- Consistent Read(일관된 읽기)의 약자
- 블록 읽기 작업시 기본적으로 CR을 수행한다.
- Query가 시작하는 시점의 SCN과 호환되는 일관된 버전의 데이터, 즉 과거 버전의 데이터를 읽는다는 것을 의미한다.
- 그림 설명
- 세션 A가 블록 X의 특정 로우를 변경하면 블록 X는 Dirty 블록이 된다.
- 세션 B가 Dirty 블록 X를 읽을려고 하면 오라클은 블록 X의 과거 버전인 CR 블록을 만들고 롤백을 수행한다.
- - 즉, Dirty상태로 되기 전의 데이터를 적용해서 과거 버전의 데이터를 만든다. (이 과정을 CR 카피라고 부른다)
- 세션 B는 이 CR 블록을 읽어 들인다.
1.1 X$BH 뷰[편집]
- 오라클에서 블록의 상태를 보는 가장 좋은 방법은 Fixed View 중 하나인 X$BH 뷰를 보는 것
- 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
4) 4/319 블록이 1번(Current) 상태로 존재함을 알 수 있다. 아직 Dirty 상태가 아니기 때문.
5) Update를 수행해서 Dirty 블록을 만든다.
Session A: UPDATE cr_test SET name = 'name2';
Session C : @xbh
--> 4/319 블록에 대해 CR 블록(State=3)이 생겼음을 알 수 있다. 즉 Update에 의해 Dirty 블록을 만들어지는 시점에 오라클은 하나의 CR 카피본을 만든다.
6) 이제 Session B에서 Dirty 블록에 대해 읽기를 수행한다.
Session B : select * from cr_test;
--> CR 블록이 하나 더 생겼음을 알 수 있다(맨위). 이 CR 블록은 기존의 CR블록(SCN_BAS가 399558603인)의 카피본이며 실제 롤백시 수행되었음(CR_UBA_FIL = 2)을 알 수 있다.
7) Session B 에서 십여 차례 select * from cr_test 쿼리를 수행한다.
--> CR 블록이 최대 5개까지만 만들어지는 것을 확인할 수 있다. Select 요청이 있을 때마다 가장 가까운 CR 블록을 이용해 새로운 CR 카피본을 만들고 필요한 경우 롤백을 수행한다. 5개를 초과하면 가장 오래된 CR 블록은 밀려난다. 이 값은 _DB_BLOCK_MAX_CR_DBA 파마리터에 의해 결정된다.
8) 아래 결과는 Session B에서 계속해서 Select를 수행한 결과인데 CR_SCN_BAS가 최근 값을 모두 바뀐 것을 확인할 수 있다.
오라클이 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 블록을 계속 갱신하면서 유지하는가?
- 이에 대한 대답은 CR 작업을 좀 더 효율적으로 하기 위해서이다. 즉, 최대 5개까지 가장 최근의 CR 블록을 유지함으로써 과거 버전 읽기 작업에 드는 부하를 최소화하기 위함이다.
- 오라클은 Select 요청에 맞는 CR 블록을 생성하기 위해 CR 카피를 만들고, Undo로부터 롤백을 수행하는 일련의 작업을 수행하는데, 이 작업의 부하를 최소화하기 위해 버퍼 캐시에 최근의 CR 블록을 여러 개 유지하는 것이다.
2) 하나의 블록당 여러 개의 CR 블록을 유지함으로써 메모리의 낭비를 유발하지 않는가?
- 실제로 그렇다. 오라클의 특정 버전에서는 CR 블록 수가 너무 많아져서 버퍼 캐시의 효율성이 떨어지는 현상이 실제로 있었다.
- 하지만 최신 버전의 오라클은 CR 블록의 위치를 LRU 리스트의 꼬리쪽으로 위치시킴으로써 메모리 부족 현상이 생길때 되도록 빨리 밀려나도록 해준다.
- 오라클의 CR 블록과 Consistent Read는 다른 DB에서는 잘 지원하지 못하는 MVRC(Multi Versioning Read Consistency)를 가능하게 하는 핵심 메커니즘이다.
- 여러분은 오라클을 잘 알고 있다고 생각하는가!!! 그렇다면 여기서 제시한 CR 작업에 대한 이해를 여러분의 지식 주머니안에 넣고 다녀야 할 것이다. ^^
- 더불어 아래에 필자가 저술한 책을 한번씩 읽어 보길 권한다. 책 광고 아니냐고? 책 광고 맞다. 하지만 읽게 되면 여러분의 내공이 아마 한 갑자 정도는 늘어날 것이다...