3. Library Cache 구조
1) Library cache 개요
- 위치 : Shared Pool 내부
- 용도 : SQL 커서, DB Object 등에 대한 정보 관리(컴파일된 함수, 프로시져, 패키지 등등)
--> Library cache 안의 위 정보들을 LCO(Library Cache Object) 라고 지칭 - 분류1 : 실행 가능 LCO - 오브젝트 LCO
- 분류2 : 영구 보관되는 LCO와 인스턴스 떠 있는 동안만 존재하는 임시 LCO 로도 구분 가능(커서 등)
- 옵젝트 정보가 딕셔너리 캐시에도 있는데 LC 에도 있는 이유는 의존성(Dependency) 관리 때문
--> LCO 각각은 자신을 참조하는 다른 실행가능 LCO 목록을 가진다
2) Library cache 특성
- 쉐어드 풀 안의 할당된 공간 사용, LRU 알고리즘으로 관리 됨
- 버퍼 캐시처럼 해시 구조로 관리
- 해시 버킷에 LCO 핸들이 체인 구조로 연결되며, 각 핸들이 힙 메모리 안의 실제 옵젝트를 지정
- 힙 메모리 안의 커서 Object 에는 딸려 있는 차일드 커서 정보 가지고 있음
Library cache 관리를 위한 보호 메커니즘
- Shared pool latch: 쉐어드 풀 안의 프리청크 할당받을 때 필요한 래치
7개의 래치가 여러개의 서브 풀을 관리한다 - Library cache latch: 라이브러리 캐시 체인탐색 및 변경을 위해 필요한 래치
- Library cache lock: 해시 체인의 LCO 핸들 각각에 거는 락, 이 락을 걸어야 실제 힙 메모리에 접근 가능
- Library cache pin: 힙 안의 실제 LCO 를 읽거나 변경할 때 이용
타 세션에 의한 변경이나 캐싱에서 밀려나는것 방지
Shared pool latch/Library cache latch 경합은 는 하드/소프트 파스 경합에 의해
Library cache lock/Library cache pin 경합은 SQL 수행 도중 DDL 동시 수행 시 발생
3) 결론은...
- 커서 공유가 가능하 형태로 SQL 작성 할 것
- 세션 커서 캐싱 기능 이용해 LC 에서 SQL 찾는 비용 줄일 수 있음
- 어플리케이셔 커서 캐싱 이용해 Parse Call 발생량을 줄일 수 있음
부록
Library cache lock/pin
Library cache Lock
- 역할: LCO 핸들을 보호
- LC Lock의 세 가지 모드
Shared : 읽기 작업 시 획득
Exclusive : LCO 생성/변경 시 획득
Null : Object 간 의존성 관리에 사용, Lock 을 장시간 유지 가능함
Null Mode Lock?
- Parse Lock 이라고도 함
- 실행 가능 LCO 에 대해서만 설정 가능
- 대기 없이 바로 해제할 수 있다
- 실행 가능 LCO 는 참조하는 각 LCO 에 대해 Null mode 의 락을 걸고 있으며
Schema Object 변경 시 참조하는 LCO 에 설정 된 Lock 을 해제 함으로써 Invalidation 되었다고 알려주는 역할 - SQL, PL/SQL 이 처음 수행되며 파싱 되는 시점에 걸리고
Shared SQL area 가 Shared pool 에 남아 있는 한 계속 유지 됨
Library cache Pin
- 역할: LCO 핸들이 아닌 실제 힙 영역을 보호함
핀을 획득해야 읽기, 실행, 변경 가능함(정보를 새로 가져올 때도 Pin 획득 필요)
- LC Pin 의 두 가지 모드
Shared : 힙 영역의 읽기 작업 시 획득
Execlusicve : 힙 경역의 변경, 신규 생성 시 획득(Shared 모드 잠깐 획들 했다가 Execlusive 모드로 변경 한다고 함) - Pin은 힙 영역에서 관리 하지만 Pin 소유자/대기자 목록은 핸들 쪽에서 관리
SQL> alter session set events '10046 trace name context forever, level 12';
Session altered.
SQL> var v1 number;
SQL> begin :v1 := 1983; end;
2 /
PL/SQL procedure successfully completed.
SQL> select b from pin_test where b = :v1;
B
----------
1983
1983
SQL> begin :v1 := 1984 ; end;
2 /
PL/SQL procedure successfully completed.
SQL> select b from pin_test where b = :v1;
B
----------
1984
1984
SQL> begin :v1 := 1985 ; end;
2 /
PL/SQL procedure successfully completed.
SQL> select b from pin_test where b = :v1;
B
----------
1985
1985
SQL> exit
[TEST10]/lim/admin/TEST10/udump> tkprof test10_ora_13844.trc
output = lc_test.txt
TKPROF: Release 10.2.0.4.0 - Production on Sat May 12 02:12:27 2012
Copyright (c) 1982, 2007, Oracle. All rights reserved.
[TEST10]/lim/admin/TEST10/udump> vi lc_test.txt
********************************************************************************
select b
from
pin_test where b = :v1
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 3 0.00 0.00 0 0 0 0
Execute 3 0.00 0.00 0 1 0 0
Fetch 6 0.41 0.40 838 24990 0 6
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 12 0.41 0.40 838 24991 0 6
Misses in library cache during parse: 1
Misses in library cache during execute: 1
Optimizer mode: ALL_ROWS
Parsing user id: 58
Rows Row Source Operation
------- ---------------------------------------------------
2 TABLE ACCESS FULL PIN_TEST (cr=8330 pr=191 pw=0 time=33841 us)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 6 0.00 0.00
db file sequential read 207 0.00 0.00
db file scattered read 189 0.00 0.00
SQL*Net message from client 5 13.59 25.13
********************************************************************************
LCO 핸들과 힙 영역의 구분으로 인해 발생 가능한 예외 상황 1
- LCO 핸들을 해시 버킷에서 존재하지만 실제 Pointer 가 가르키는 힙 영역에는 내용이 없는 경우
--> 힙 영역은 LRU 알고리즘에 의해 관리되어 정보가 밀려날 수 있음
--> LCO 핸들에 대해 Lock 획득은 성공, 실행 단계에서 LC Pin 획득 후 새로 캐싱
- 위와 같은 상황이 발생하고 Execution 단계에서의 블록 읽기가 과도한 경우는
메모리 사이즈가 작거나 잦은 하드 파싱으로 인해 힙 영역에서 LC Object 가 자주 밀려나는 경우
LCO 핸들과 힙 영역의 구분으로 인해 발생 가능한 예외 상황 2
- Parse 단계에서 LCO 핸들에 대한 조회 실패/Execute 단계에서 SQL 힙 영역의 Object 조회 실패 동시 발생
- Parse 단계에서 LCO 핸들 조회 실패 시 핸들/힙 정보를 새로 캐싱하므로 일반적인 상황에서는 발생하지 않음
서로 다른 SQL 커서 LCO 간 '실행계획' 의 공유로 인해 발생하는 현상
- SQL 커서와 SQL 실행 계획은 Library cache 에서 별도로 관리 됨
- 첫 하드 파싱 때 SQL 커서를 새로 캐싱 하였으나 기존에 존재하는 실행계획의 재 사용이 가능하여
실행 계획 LCO 핸들에 대해 Pointer 를 연결 하였으나 힙 영역 안의 실행 계획은 밀려나고 없을 경우 (예외 1번 상황)
Lock 과 pin 을 별도로 사용하는 이유?
Handle 은 Fixed 영역이나 Heap 은 동적으로 관리되므로 밀려날 가능성 존재
의존 관계에 있는 Object 들 간에 동시성 보장 가능
- SQL이나 PL/SQL 실행 시 참조하는 오브젝트의 의존성 정보는 LCO 핸들의 Parse Lock 으로 관리
- SQL이나 PL/SQL 실행 시 참조하는 오브젝트의 읽기(혹은 실행)는 힙 영역에 Pin 으로 관리
- Pin걸고 사용중인 LCO 간에도 Parse Lock 해제는 자유롭게 가능하다
--> SQL 실행 중에도 참조하는 오브젝트에 대한 DDL 이 가능
create table pin_test (b number);
begin
for i in 1 .. 1500000 loop
insert into pin_test (b) values ( i);
end loop;
commit;
end;
------------------------------------
*[Session 1]*
create or replace function pin_test_f
return number
is
v_rslt number ;
begin
select sum((q.b + t.b)/(q.b*t.b) + (q.b*t.b)/(q.b/t.b)) into v_rslt from
(select b from pin_test) q,
(select b from pin_test) t
where q.b=t.b+1;
return v_rslt;
end;
/
SQL> select pin_test_f from dual;
PIN_TEST_F
----------
1.1250E+18
SQL>
*[Session 2]*
SQL> alter table pin_test add (d number(5));
Table altered.
SQL> alter table pin_test modify b number(10);
Table altered.
SQL>