[아이티윌 오라클 DBA 과정 91기] 260126 TIL

2026. 1. 29. 09:21Courses/아이티윌 오라클 DBA 과정

Database(Data) Buffer Cache(Cont.)

세그먼트 헤더 블록

  • 익스텐트 맵
  • HWM

물리적 I/O 발생

  • access하려는 블록이 데이터 버퍼 캐시에 없을 경우 물리적 I/O 발생
  • working set을 관리하는 cache buffers lru chain latch를 획득해야 함
  • 이 과정에서 경합이 발생하면 latch: cache buffers lru chain 대기 이벤트 발생
SYS@ora19c> select count(*) from v$latch_children where name = 'cache buffers lru chain';

  COUNT(*)
----------
        36

SYS@ora19c> select a.ksppinm parameter, b.ksppstvl value
from x$ksppi a, x$ksppcv b
where a.indx = b.indx
and a.ksppinm = '_db_block_lru_latches';  2    3    4

PARAMETER                                                                        VALUE
-------------------------------------------------------------------------------- ------------------------------
_db_block_lru_latches                                                            18        

SYS@ora19c> select a.bp_blksz,
       c.child#,
       a.bp_name,
       c.gets,
       c.MISSES,
       c.SLEEPS
    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
 order by 1,2;  2    3    4    5    6    7    8    9   10

  BP_BLKSZ     CHILD# BP_NAME                    GETS     MISSES     SLEEPS
---------- ---------- -------------------- ---------- ---------- ----------
      2048         13 DEFAULT                      16          0          0
      2048         15 DEFAULT                      16          0          0
      4096         17 DEFAULT                      16          0          0
      4096         19 DEFAULT                      16          0          0
      8192          1 KEEP                         16          0          0
      8192          3 KEEP                         16          0          0
      8192          5 RECYCLE                      16          0          0
      8192          7 RECYCLE                      16          0          0
      8192          9 DEFAULT                   90844         11          4 <<- 실제 사용하는 cache buffer lru chain latch
      8192         11 DEFAULT                   85581          7          0 <<- 실제 사용하는 cache buffer lru chain latch
      8192         21 DEFAULT                      16          0          0
      8192         23 DEFAULT                      16          0          0
      8192         33 DEFAULT                      16          0          0
      8192         35 DEFAULT                      16          0          0
     16384         25 DEFAULT                      16          0          0
     16384         27 DEFAULT                      16          0          0
     32768         29 DEFAULT                      16          0          0
     32768         31 DEFAULT                      16          0          0

18 rows selected.
  • LRU List의 보조 리스트에서 free buffer를 찾음
  • 만약에 보조 리스트에 free buffer가 없을 경우 메인 리스트 cold 영역 제일 뒤에서부터 free buffer를 찾음
  • 찾는 도중에 touch count가 1 이하인 버퍼가 free buffer로 사용될 수 있음
  • 만약에 찾는 도중에 touch count가 2 이상인 버퍼를 만나면 hot 영역 앞으로 옮기고 해당 버퍼 touch count는 0으로 초기화시킴
# touch count가 2 이상인 buffer를 만나면  hot region 으로 옮겨지는 기준
SYS@ora19c> select a.ksppinm parameter, b.ksppstvl value
from x$ksppi a, x$ksppcv b
where a.indx = b.indx
and a.ksppinm = '_db_aging_hot_criteria';  2    3    4

PARAMETER                                                                        VALUE
-------------------------------------------------------------------------------- ------------------------------
_db_aging_hot_criteria                                                           2
  • LRU List에서 free buffer를 40% scan 하고도 free buffer를 찾지 못하면 DBWR에게 dirty buffer 들을 데이터 파일에 기록하고 free buffer를 확보해 줄 것을 요청
SYS@ora19c> select a.ksppinm parameter, b.ksppstvl value
from x$ksppi a, x$ksppcv b
where a.indx = b.indx
and a.ksppinm = '_db_block_max_scan_pct';  2    3    4

PARAMETER                                                                        VALUE
-------------------------------------------------------------------------------- ------------------------------
_db_block_max_scan_pct                                                           40
  • free buffer를 찾게 되면 해당 버퍼에 대해 buffer lock을 exclusive 모드로 획득하고 데이터 파일에서 블록을 해당 위치로 읽어 들임
  • logical I/O 수 안에 physical I/O도 포함
  • touch count는 3초 후에 다시 access 하게 되면 1씩 증가
SYS@ora19c> select a.ksppinm parameter, b.ksppstvl value
from x$ksppi a, x$ksppcv b
where a.indx = b.indx
and a.ksppinm = '_db_aging_touch_time';  2    3    4

PARAMETER                                                                        VALUE
-------------------------------------------------------------------------------- ------------------------------
_db_aging_touch_time                                                             3

working set

  • 데이터 버퍼 캐시 관리
  • LRU(Least Recently Used) List
    • 가장 최근에 사용되거나 사용하지 않은 버퍼들의 리스트
    • free buffer, 사용 중이거나 사용된 버퍼, 아직 LRUW 리스트로 옮겨지지 않은 dirty block
    • 메인 리스트 : 사용된 버퍼들의 리스트
    • 보조 리스트 : free buffer list, 미사용된 buffer, dbwr에 의해 기록된 버퍼들의 리스트
  • LRUW(Least Recently Used Write) List, Dirty List
    • 아직 데이터 파일로 기록되지 않은 변경된 버퍼(dirty buffer)들을 관리하는 리스트
    • 메인 리스트 : 변경된 buffer들의 리스트
    • 보조 리스트 : 현재 dbwr에 의해 기록 중인 버퍼들의 리스트(partial checkpoint 시 이 부분만 봐도 됨)
    • LRU 리스트에서 free buffer를 더 이상 찾을 수 없는 경우 체크 포인트를 발생시켜 dirty buffer를 디스크에 작성해야 함
    • dirty block들을 빠르게 찾기 위해 LRUW list 탐색

실습

Buffer Cache flush

alter system flush buffer_cache;

buffer cache에 올라와 있는 버퍼 정보 조회

# HR 유저가 소유한 Object 블록 중 버퍼 캐시에 올라가 있는 블록 조회
select o.object_name, x.obj, x.file#, x.dbablk, x.tch, x.state 
from x$bh x, dba_objects o
where o.data_object_id = x.obj
and o.owner = 'HR';

  • touch count 정보는 x$bh의 TCH 컬럼을 통해 조회 가능
  • state = 1은 v$bh에서 status = xcur과 동일 : 사용 중인 블록
select o.object_name, x.objd, x.file#, x.block#, x.status
from v$bh x, dba_objects o
where o.data_object_id = x.objd
and o.owner = 'HR';

select * from dba_segments where segment_name = 'EMP_EMP_ID_PK';

  • root 블록은 세그먼트 헤더 블록의 다음 번호를 가짐

물리적 I/O 발생

테이블 생성

drop table hr.emp purge;
create table hr.emp(id number, name varchar2(1000)) tablespace users;
insert into hr.emp(id, name)
select level, 'oracle'||level
from dual
connect by level < = 1000000
order by dbms_random.value;

commit;

SYS@ora19c> select blocks, bytes/1024/1024 mb from dba_segments where owner = 'HR' and segment_name = 'EMP';

    BLOCKS         MB
---------- ----------
      3328         26

인덱스 생성

create index hr.emp_idx on hr.emp(id) tablespace users;

SYS@ora19c> select blocks, bytes/1024/1024 mb from dba_segments where owner = 'HR' and segment_name = 'EMP_IDX';

    BLOCKS         MB
---------- ----------
      2304         18      

세션 1, 2에서 아래 익명 블록 수행 : 인덱스 스캔

 begin
    for i in (select /*+ index(e emp_idx) */* from hr.emp e where id >= 0) loop
        null;
    end loop;
 end;
 /
SYS@ora19c> select sid, event, total_waits, time_waited
from v$session_event
where sid in (select sid from v$session where username = 'HR');  2    3

       SID EVENT                                                            TOTAL_WAITS TIME_WAITED
---------- ---------------------------------------------------------------- ----------- -----------
        38 log file sync                                                              1           0
        38 SQL*Net message to client                                                  8           0
        38 SQL*Net message from client                                                7           1
        38 events in waitclass Other                                                  8           0
       160 log file sync                                                              1           1
       160 SQL*Net message to client                                                  8           0
       160 SQL*Net message from client                                                7           0
       160 events in waitclass Other                                                  8           0

8 rows selected.

SYS@ora19c> /

       SID EVENT                                                            TOTAL_WAITS TIME_WAITED
---------- ---------------------------------------------------------------- ----------- -----------
        38 log file sync                                                              1           0
        38 SQL*Net message to client                                                  9           0
        38 SQL*Net message from client                                                8        4552
        38 events in waitclass Other                                                  9           0
       160 Disk file operations I/O                                                   1           0
       160 log file sync                                                              1           1
       160 db file sequential read                                                 2227           7
       160 db file parallel read                                                     95           4
       160 SQL*Net message to client                                                  9           0
       160 SQL*Net message from client                                                8        4886
       160 events in waitclass Other                                                 18           0

11 rows selected.

세션 1, 2에서 아래 익명 블록 수행 : 풀 테이블 스캔

 begin
    for i in (select /*+ full(e) */* from hr.emp e where id >= 0) loop
        null;
    end loop;
 end;
 /
SYS@ora19c> select sid, event, total_waits, time_waited
from v$session_event
where sid in (select sid from v$session where username = 'HR');  2    3

       SID EVENT                                                            TOTAL_WAITS TIME_WAITED
---------- ---------------------------------------------------------------- ----------- -----------
       162 Disk file operations I/O                                                   1           0
       162 log file sync                                                              1           1
       162 db file sequential read                                                    1           0
       162 SQL*Net message to client                                                  8           0
       162 SQL*Net message from client                                                7           1
       162 events in waitclass Other                                                  9           0
       160 Disk file operations I/O                                                   2           0
       160 log file sync                                                              1           3
       160 db file sequential read                                                    9           0
       160 SQL*Net message to client                                                  8           0
       160 SQL*Net message from client                                                7           1
       160 events in waitclass Other                                                  9           0

12 rows selected.

SYS@ora19c> /

       SID EVENT                                                            TOTAL_WAITS TIME_WAITED
---------- ---------------------------------------------------------------- ----------- -----------
       162 Disk file operations I/O                                                   2           0
       162 log file sync                                                              1           1
       162 db file sequential read                                                    1           0
       162 direct path read                                                         107           1
       162 SQL*Net message to client                                                  9           0
       162 SQL*Net message from client                                                8        1855
       162 events in waitclass Other                                                 13           0
       160 Disk file operations I/O                                                   3           0
       160 log file sync                                                              1           3
       160 db file sequential read                                                   13           0
       160 db file scattered read                                                     1           0
       160 direct path read                                                         107           1
       160 SQL*Net message to client                                                  9           0
       160 SQL*Net message from client                                                8        2098
       160 events in waitclass Other                                                 16           0

15 rows selected.
  • direct path read 방식 사용

세션 1, 2에서 아래 익명 블록 수행 : direct path read X

# direct path read를 사용하지 않도록 event 설정
alter session set events '10949 trace name context forever, level 1';

begin
    for i in (select /*+ full(e) */* from hr.emp e where id >= 0) loop
        null;
    end loop;
end;
/
SYS@ora19c> select sid, event, total_waits, time_waited
from v$session_event
where sid in (select sid from v$session where username = 'HR');  2    3

       SID EVENT                                                            TOTAL_WAITS TIME_WAITED
---------- ---------------------------------------------------------------- ----------- -----------
       162 Disk file operations I/O                                                   1           0
       162 log file sync                                                              1           1
       162 db file sequential read                                                    3           0
       162 SQL*Net message to client                                                  9           0
       162 SQL*Net message from client                                                8        5920
       162 events in waitclass Other                                                 11           0
       160 Disk file operations I/O                                                   3           0
       160 log file sync                                                              1           1
       160 SQL*Net message to client                                                  9           0
       160 SQL*Net message from client                                                8        4866
       160 events in waitclass Other                                                 10           0

11 rows selected.

SYS@ora19c> /

       SID EVENT                                                            TOTAL_WAITS TIME_WAITED
---------- ---------------------------------------------------------------- ----------- -----------
       162 Disk file operations I/O                                                   2           0
       162 log file sync                                                              1           1
       162 db file sequential read                                                    6           0
       162 db file scattered read                                                    91           3
       162 SQL*Net message to client                                                 10           0
       162 SQL*Net message from client                                                9       10196
       162 events in waitclass Other                                                 11           0
       160 Disk file operations I/O                                                   3           0
       160 log file sync                                                              1           1
       160 SQL*Net message to client                                                 10           0
       160 SQL*Net message from client                                                9        9126
       160 events in waitclass Other                                                 10           0

12 rows selected.

Single Block I/O 수행 시 발생

  • rowid scan 발생(root → branch → leaf → rowid 를 이용해서 테이블 스캔)
  • 데이터 파일 헤더(file header)
  • row chaining, row migration
  • db file sequential read : 데이터 파일로부터 하나의 블록을 메모리로 읽는 작업(물리적 I/O)
  • db file parallel read
    • prefetch 기능이 수행될 경우
    • Single Block I/O 수행 시 디스크에서 읽어야 하는 경우가 생기면 바로 디스크로 가지 않고 디스크에서 읽어야 하는 블록들을 모아 놨다가 한 번에 읽어옴

Multi Block I/O 수행 시 발생

  • table full scan, index fast full scan
  • db file scattered read : 데이터 파일로부터 여러 개의 블록을 메모리로 읽는 작업(물리적 I/O)
    • 낮 시간, OLTP 시스템에서 이 이벤트가 발생하면 확인 및 조치 필요
    • 밤 시간, OLAP 시스템에서는 이 이벤트가 발생하는 것이 당연
  • direct path read
    • Multi Block I/O 발생 시 데이터 버퍼 캐시에 올리지 않고 서버 프로세스에 있는 CURSOR에 직접 읽어오는 방식

Transaction 처리 순서

SYS@ora19c> select s.username, t.xidusn, t.ubafil, t.ubablk, t.used_ublk
from v$session s, v$transaction t
where s.saddr = t.ses_addr;  2    3

no rows selected

# 트랜잭션 시작
HR@ora19c> update hr.employees set salary = salary * 1.1 where employee_id = 200;

1 row updated.

SYS@ora19c> /

USERNAME                           XIDUSN     UBAFIL     UBABLK  USED_UBLK
------------------------------ ---------- ---------- ---------- ----------
HR                                      2          4       1412          1
SYS@ora19c> col object_name format a30
SYS@ora19c> select o.object_name, x.obj, x.file#, x.dbablk, x.tch, x.state
from x$bh x, dba_objects o
where o.data_object_id = x.obj
and o.owner = 'HR'
and o.object_name = 'EMPLOYEES';  2    3    4    5

OBJECT_NAME                           OBJ      FILE#     DBABLK        TCH      STATE
------------------------------ ---------- ---------- ---------- ---------- ----------
EMPLOYEES                           72977          3      31277          0          0
EMPLOYEES                           72977          3      31274          0          0
EMPLOYEES                           72977          3      31279          1          1
EMPLOYEES                           72977          3      31279          0          0

Undo 정보 조회

SYS@ora19c> select n.usn, n.name, s.extents, s.rssize, s.xacts, s.status
from v$rollname n, v$rollstat s
where n.usn = s.usn;  2    3

       USN NAME                                                  EXTENTS     RSSIZE      XACTS STATUS
---------- -------------------------------------------------- ---------- ---------- ---------- ---------------
         0 SYSTEM                                                      7     450560          0 ONLINE
         1 _SYSSMU1_1261223759$                                        4    2220032          0 ONLINE
         2 _SYSSMU2_27624015$                                          4    2220032          1 ONLINE
         3 _SYSSMU3_2421748942$                                        8     516096          0 ONLINE
         4 _SYSSMU4_625702278$                                         5    3268608          0 ONLINE
         5 _SYSSMU5_2101348960$                                        6    3334144          0 ONLINE
         6 _SYSSMU6_813816332$                                         4    2220032          0 ONLINE
         7 _SYSSMU7_2329891355$                                        5    3268608          0 ONLINE
         8 _SYSSMU8_399776867$                                         4    2220032          0 ONLINE
         9 _SYSSMU9_1692468413$                                        5    3268608          0 ONLINE
        10 _SYSSMU10_930580995$                                        5    3268608          0 ONLINE

11 rows selected.

DML 처리 단계

  1. parse
  2. bind
  3. execute
    • library cache lock과 library cache pin 을 share mode로 변경
    • 트랜잭션 시작

트랜잭션 처리 순서

1. undo segment 할당

  • 현재 온라인 상태인 undo 세그먼트 중 하나를 사용(랜덤)
  • 다른 트랜잭션이 사용 중이라면 오라클은 3번까지 재시도
  • 이 과정에서 실패하게 되면 오프라인 상태의 undo 세그먼트를 온라인으로 사용
  • 이 과정에서도 실패하게 되면 새로운 undo 세그먼트(10개 기본)를 생성해서 사용(undo 테이블스페이스에 속한 데이터 파일 여유 공간이 있을 경우)
  • 이 과정에서도 실패하게 되면 사용 중인 undo 세그먼트 중 가장 사용량이 작은 undo 세그먼트를 같이 사용
  • undo segment를 할당 받기까지 enq: US - contention 대기 이벤트 발생

2. undo segment header block에 transaction table slot 생성

  • 트랜잭션 정보를 저장하는 곳, txid(transaction id)를 생성
  • txid = (xidusn, xidslot, xidsqn)
SYS@ora19c> select t.xidusn, xidslot, xidsqn
from v$session s, v$transaction t
where s.saddr = t.ses_addr;  2    3

    XIDUSN    XIDSLOT     XIDSQN
---------- ---------- ----------
         2          5       2491

3. 트랜잭션 대상이 되는 블록을 데이터 버퍼 캐시에서 실행 계획을 통해 찾음

  • cache buffers chains latch
    • 인덱스 블록은 shared mode로 획득
    • 대상 데이터 블록은 exclusive mode로 획득
  • block(buffer) header에 block lock(shared(select), exclusive(dml))을 획득한 후 cache buffers chains latch를 해제
    • buffer header에 block lock 경합이 발생하면 buffer busy waits 대기 이벤트 발생
  • block header에 있는 transaction layer에 transaction slot을 획득해야 함(ITL(Interested Transaction List)에 transaction entry 등록)
  • 만약에 ITL entry(transaction slot)을 획득할 수 없으면 enq : TX - allocate ITL entry 대기 이벤트가 발생
  • 트랜잭션 대상 행에 대해서 lock 생성
  • 만약 다른 세션에서 같은 행을 lock 걸고 있으면 기다려야 함
  • 이 때 발생하는 대기 이벤트는 enq : TX - row lock contention

4. 변경 정보를 PGA 영역에 change vector 생성

  • undo segment header 정보(change vector #1)
  • undo block (change vector #2)
  • transaction 대상이 되는 블록(change vector #3)
  • PGA 영역 안에 있는 change vector 를 redo entry라는 이름으로 redo log buffer로 복사
  • redo copy latch, redo allocation latch, redo writing latch를 획득해야 함
  • 이 과정에서 latch 경합이 발생하면
    • latch: redo copy
    • latch: redo allocation
    • latch: redo writing

5. 이전 값은 undo block에 작성하고 새로운 값으로 변경

  • 변경된 블록은 dirty 상태가 됨
  • 블록 header에 있는 buffer lock(exclusive)은 해지