====== Buffer Cache 란 ======
- 오라클은 물리적인 I/O를 최소화 하기 위해 최근에 사용된 블럭에 대한 정보를 메모리의 일정 부분에 보관하려 한다 => 이 영역을 Buffer Cache 라고함.
===== Buffer Cache 구조 =====
{{:study:oracle:adv_owi_10g:1.jpg|}}
- Hash Chain 구조의 시작점은 Hash Table인데, Hash Table은 Hash Bucket으로 구성되어져 있다
- 오라클 블럭(DBA: Data Block Address File# , Block# )과 블럭 클래스 에 대한 Hash 함수 결과 값으로 해당 Hash Bucket을 찾아가서 해당 데이터 블럭이 메모리에 존재 하는지를 확인 할 수 있는 것 이다
- Hash Bucket에 딸린 Buffer Header는 Buffer에 대한 메타 정보만 가지고 있고 Buffer 메모리 영역의 실제 버퍼에 대한 포인터 값을 가지고 있다.
- Hash Chain 구조는 Shared Pool 영역에 존재 하며 실제 버퍼에 대한 정보들은 버퍼 캐쉬 영역에 존재 한다
- 특정 블럭에 대한 Scan을 할려고 하면 Cache buffer chains latch를 획득 해야만 한다. \\ **※ 9i부터 읽기 작업에 한하여 buffer cache chains latch를 shared 모드로 획득 한다**
- 다음과 같은 쿼리를 이용하여 cache buffer chains latch의 갯수를 확인가능 하다 \\
SQL> select count(*) from v$latch_children where name = 'cache buffers chains'
COUNT(*)
----------
65536
* **cache buffer chains latch** => hash 함수로 얻은 값으로 해당 데이터가 어떠한 bucket에 있는가를 확인할때 발생되는 latch
{{:study:oracle:adv_owi_10g:4.jpg|}}
==== Working Set ====
* 오라클은 Buffer Cache에 대하여 효율적으로 사용하기 위해 두 종류의 LRU리스트를 사용한다.
{{:study:oracle:adv_owi_10g:3.jpg|}}
- LRU List : 가장 최근에 사용되거나 미사용된 버퍼들의 List
- Free(미사용) , 사용중이거나 사용된 버퍼 아직 LRUW로 옮겨지지 않은 Dirty 버퍼
- 메인 리스트 : 사용된 버퍼들의 리스트 , 핫 영역과 콜드 영역으로 구분 관리 됨
- 보조 리스트 : 프리 버퍼들의 리스트 , 미사용 된 버퍼나 DBWn에 의해 기록 된 버퍼 관리
- LRUW List : 아직 디스크에 기록 되지 않은 Dirty한 버퍼들의 List
- 메인 리스트 : 변경된 버퍼들의 리스트
- 보조 리스트 : 현재 DBWR에 의해 기록중인 버퍼 리스트
* 다음 그림과 같이 LRU , LRUW를 합쳐서 하나의 Working Set 이라고 부른다.
{{:study:oracle:adv_owi_10g:2.jpg|}}
* Working Set 개수는 Cache buffer lru latch 개수에 의해 결정( 하나의 working set을 하나의 lru latch가 관리함 )되며 X$KCBWDS( Kerner Cache Buffer Working sets Descriptors )를 조회 하면 확인 가능 하다
* LRU , LRUW List를 탐색 하고자 하는 프로세스는 반드시 cache buffer lru chain latch를 획득 해야 함.
* **cache buffer chains lru latch** => bucket의 header chain을 검색하여 블록이 버퍼캐시안에 없을때 lru를 뒤져 free buffer을 찾기위해 발생되는 latch
==== Touch Count ====
* 오라클은 개별 버퍼 마다 Touch Count를 관리 하며 , 프로세스에 의해서 스캔이 이루어 질때 마다 Touch Count를 1씩 증가시킴
- Cold 영역의 꼬리에 있으면서 Touch Count가 1이하인 것이 Free Buffer로 사용된다.
- Cold 영역의 꼬리에 있으면서 Touch Count가 2 이상인 블럭을 만나면 Hot영역의 head 부분으로 옮기고 Touch count를 0 으로 초기화 한다.
- 핫 영역으로 옮기는 기준은 _DB_AGING_HOT_CRITERIA 파라메터 이며 기본이 2 이다.
- 만약 Single블럭 I/O에 의해 읽혀진 블럭은 Mid-Point에 삽입되며 Touch Count는 1 이다.
- Full table scan 이나 인덱스 Full Scan으로 읽혀진 데이터 들은 Mid-Point에 삽입되었다 바로 Cold 영역의 꼬리로 옮겨져서 버퍼 캐쉬에 머무를 확률이 작아 진다.
==== Buffer lock ====
* buffer 자체 보호 . 즉 , 버퍼의 내용을 변경하거나 읽으려고 하는 프로세스는 변경 작업이나 읽기 작업을 완료할때 까지 해당 버퍼 (정확하게 말하면 Buffer header)에 대해서 buffer lock을 exclusive 또는 shared 하게획득 해야 한다.
===== Buffer Cache 블록을 올리거나 버퍼캐시에 올라와있는 블록을 사용하고자 할때 =====
- sql문에 의해서 조건에 만족하는 데이터가 버퍼캐시에 존재 여부 확인하기 위해 DBA(data block address) + class(data, sort, undo)를 조합하고 > hash function을 돌려 해당 데이터가 어떠한 bucket에 있는가 확인(= DBA + class를 hash 함수로 돌린뒤 그값을통해 hash bucket를 찾음)
- cache buffer chains latch를 획득(읽기는 shared, 변경은 exclusive)
- hash bucket에서 관리하는 buffer header들(chain)을 검색하여 블록이 버퍼캐시안에 존재 하는지 확인
- 버퍼캐시안에 없을경우 cache buffer lru latch를 획득함
- LRU 보조 리스트를 통해 free buffer를 검색
- LRU 메인리스트에서 free buffer을 검색
- 검색중 dirty블럭을 만나면 LRUW 리스트의 메인 리스트에 추가
- 검색중 touch count가 2이상인 것을 만나면 hot 영역의 머리부분으로 옮기고 touch count를 0으로 세팅
- 검색중 LRU 리스트를 40% 스캔을 했는데도 free block을 찾지 못하면 LRU 스캔을 멈추고 DBWR에게 dirty 버퍼를 파일에 기록할것을 요구(_DB_BLOCK_SCAN_MAX_PCT 파라미터에 의해 %를 정함)
- DBWn에 의해서 프리버퍼가 확보 될때까지 free buffer waits 이벤트 대기
- 요청받은 DBWn은 cache buffer lru chain latch를 획득 후 LRUW 리스트의 cold 영역 꼬리부터 탐색하여 기록함
- 기록된 블럭은 LRU 보조 리스트로 옮겨짐
- free block를 찾으면 buffer lock을 exclusive하게 획득 후 데이터 파일로 부터 block를 load
===== Buffer Cache Dump =====
- 버퍼의 구조를 가장 명확하게 알 수 있는 방법은 버퍼 캐시 덤프를 이용하는것 \\
SQL> alter session set evnets 'immediate trace name buffers level 1';
OR
SQL> oradebug dump buffers 1
* 참고로 oradebug 를 추천한다 \\
- X$BH 뷰에서 확인가능하다
* 눈여겨 봐야될 컬럼은 다음과 같다
^ 컬럼 ^ 내용 ^
^ HLADDR | 해당 버퍼를 관장하는 래치의 주소 V$LATCH_CHILDREN.ADDR 과 조인해서 원하는 래치정보를 얻을수 있다 |
^ TS# | 블록이 속한 테이블스페이스 번호 V$TABLESPACE.TS# 과 조인 |
^ DBARFIL | DBA 중 파일번호 |
^ DBABLK | DBA 중 블록번호 |
^ CLASS | 블록 클래스 |
^ STATE | 버퍼의 상태 |
^ 0 | FREE no valid block image |
^ 1 | XCUR a current mode block, exclusive to this instance |
^ 2 | SCUR a current mode block, shared with other instances(RAC환경에서만 쓰임) |
^ 3 | CR a consistent read (stale) block image |
^ 4 | READ buffer is reserved for a block being read from disk |
^ 5 | MREC a block in media recovery mode |
^ 6 | IREC a block in instance (crash) recovery mode |
^ 8 | PI past image(RAC환경에서만 쓰임) |
^ TCH | Touch Count |