



execute 단계
library cache lock과 library cache pin을 shared mode로 변환하고 SQL문을 실행한다.
실행계획을 통해서 요청한 블록의 DBA(Data Block Address)와 Block class(종류)에 대해 shared pool의 해시함수에 적용한 결과를 이용해서 hash bucket을 찾는다.
latch : cache buffers chainslatch의 수
select count(*) from v$latch_children where name='cache buffers chains';

latch의 수
select a.ksppinm as parameter,b.ksppstvl as session_value, c.ksppstvl as instance_value
from x$ksppi a, x$ksppcv b, x$ksppsv c
where a.indx = b.indx
and a.indx = c.indx
and a.ksppinm = '_db_block_hash_latches';

select a.ksppinm as parameter,b.ksppstvl as session_value, c.ksppstvl as instance_value
from x$ksppi a, x$ksppcv b, x$ksppsv c
where a.indx = b.indx
and a.indx = c.indx
and a.ksppinm = '_db_block_hash_buckets';

하나의 latch가 담당하는 bucket 수는 16384/1024=16
블록 I/O시 hash bucket를 담당하는 cache buffers chains latch를 획득해야한다.
latch : cache buffers chains wait event 발생한다.같은 buffer value값을 바라보는 latch를 (exclusive, shared)로 잡는건 안되지만 (shared, shared)로 잡는건 가능하다. 하나의 latch가 멀티링크가 가능하기 때문이다.
하지만 같은 buffer value의 버퍼헤더를 (shared, shared)로 동시에 바라보는건 안된다.
물리적인 I/O발생하면 latch를 잡고 free buffer 찾는다.
이때 latch를 못잡으면latch : cache buffers lru chain wait event발생한다.
select count(*) from v$latch_children where name='cache buffers lru chain';

select a.ksppinm as parameter,b.ksppstvl as session_value, c.ksppstvl as instance_value
from x$ksppi a, x$ksppcv b, x$ksppsv c
where a.indx = b.indx
and a.indx = c.indx
and a.ksppinm = '_db_block_lru_latches';

select a.bp_blksz, c.child#, a.bp_name, c.gets
from x$kcbwbpd a, x$kcbwds b, v$latch_children c
where b.set_id between a.bp_lo_sid and a.bp_hi_sid
and c.addr = b.set_latch;

개개의 버퍼풀은 각각의 독립적인 cache buffers lru chain latch를 사용한다.
물리적인 I/O가 발생하면 cache buffers lru chain latch를 잡고 LRU LIST의 보조 리스트 에서 free buffer를 찾는다.
만약 보조 리스트의 버퍼가 모두 사용된 경우에는(즉 free buffer가 없을 경우) 메인리스트의 COLD REGION 제일 뒤에서 부터 free buffer를 찾는다.
free scan 도중에 touch count(TCH)가 1이하인 buffer를 free buffer로 사용할 수 있다.
free scan 도중에 touch count(TCH)가 2이상인 buffer를 만나면 HOT REGION 앞으로(HEAD) 옮기고 해당 buffer의 touch count(TCH)는 0으로 초기화 시킨다.
free scan 도중에 dirty buffer를 발견하면 LRUW LIST 이동시킨다.(후에 DBWR이 디스크로 dirty buffer를 내릴때 편하게 하기 위함)
free buffer를 찾게 되면 해당 버퍼에 대해 buffer lock을 exclusive mode로 획득하고 데이터 파일의 블록을 해당 버퍼로 읽어 들인다.
물리적으로 읽어 들이고 있는 중에 다른 세션에서 같은 버퍼헤더을 조회하려고 하는 경우 기다리는 작업이 발생한다. 이때 대기하는 이벤트는 read by other session wait event가 발생한다.
물리적인 I/O 발생시에 LRU 메인 리스트를 40%까지 free buffer를 찾는데, 못찾을 경우에 서버프로세스는 DBWR에게 dirty buffer를 파일에 기록하도록 요청한다.
DBWR가 dirty buffer를 파일에 기록할때 까지는 free buffer wait event가 발생한다.
LRU LIST free buffer를 40% 스캔
select a.ksppinm as parameter,b.ksppstvl as session_value, c.ksppstvl as instance_value
from x$ksppi a, x$ksppcv b, x$ksppsv c
where a.indx = b.indx
and a.indx = c.indx
and a.ksppinm = '_db_block_max_scan_pct';

select a.ksppinm as parameter,b.ksppstvl as session_value, c.ksppstvl as instance_value
from x$ksppi a, x$ksppcv b, x$ksppsv c
where a.indx = b.indx
and a.indx = c.indx
and a.ksppinm = '_db_aging_hot_criteria';

select a.ksppinm as parameter,b.ksppstvl as session_value, c.ksppstvl as instance_value
from x$ksppi a, x$ksppcv b, x$ksppsv c
where a.indx = b.indx
and a.indx = c.indx
and a.ksppinm = '_db_aging_touch_time';

BLOCK I/O에 대한 정리