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

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

Latch(Cont.)

Library Cache Pin

  • LCO에 접근하거나 변경하는 경우 LCO에 대해 획득하는 LOCK
  • LCO 실행 정보를 보호 즉 실행 과정 동안 LCO의 실행 정보가 변경되는 것을 방지
  • SQL 문 hard parsing : library cache pin을 exclusive mode로 획득 후 실행 계획을 생성
  • SQL 문 execute 단계 : library cache pin을 shared mode 획득
  • SQL 문 fetch 단계 : library cache pin을 해제
  • procedure/function/package 실행 : library cache pin을 shared mode로 획득
  • procedure/function/package 변경, 컴파일 : library cache pin을 exclusive mode로 획득

Shared Pool Latch

  • hard parsing이 발생하는 경우 free chunk를 찾기 위해 free list를 탐색하고 적절한 free chunk를 할당하고 필요한 경우 free chunk를 분할(split)하는 일련의 작업이 모두 shared pool latch를 획득한 후에만 가능
  • shared pool latch를 획득하는 과정에서 경합이 발생하면 latch : shared pool 대기 이벤트가 발생
  • shared pool latch는 기본적으로 instance당 하나만 존재
  • 9i 버전부터는 shared pool 을 여러 개의 서브 풀로 최대 7개까지 나누어서 관리하며 오라클은 CPU 개수가 4개 이상이고 shared pool 크기가 250M 이상인 경우에 _kghdsidx_count 히든 파라미터 값만큼 서브 풀을 생성해서 관리함
  • 각 서브 풀마다 shared pool latch가 만들어지기 때문에 그만큼 경합을 줄일 수 있음
# _kghdsidx_count 히든 파라미터 조회
SYS@ora19c> select a.ksppinm parameter, b.ksppstvl value
from x$ksppi a, x$ksppcv b
where a.indx = b.indx
and a.ksppinm = '_kghdsidx_count';  2    3    4

PARAMETER                                                                        VALUE
-------------------------------------------------------------------------------- ------------------------------
_kghdsidx_count                                                                  1
# shared pool latch 조회
SYS@ora19c> select name, gets from v$latch_children where name = 'shared pool';

NAME                                                     GETS
-------------------------------------------------- ----------
shared pool                                                56
shared pool                                                56
shared pool                                                56
shared pool                                                56
shared pool                                                56
shared pool                                                56
shared pool                                           4823526 <<- 사용하고 있는 shared pool latch

7 rows selected.
# cpu 수 조회
SYS@ora19c> show parameter cpu_count

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
cpu_count                            integer     2

실습

HR@ora19c> declare
        v_cnt number;
begin
        for i in 1..5 loop
                execute immediate 'select count(*) from dual where dummy = to_char('||i||')' into v_cnt;
        end loop;
end;
/  2    3    4    5    6    7    8

PL/SQL procedure successfully completed.

SYS@ora19c> select sql_id, sql_text, parse_calls, loads, executions, invalidations
from v$sql
where sql_text like '%select count(*) from dual where dummy%'
and sql_text not like '%v$sql%';

SQL_ID        SQL_TEXT                                                PARSE_CALLS      LOADS EXECUTIONS INVALIDATIONS
------------- ------------------------------------------------------- ----------- ---------- ---------- -------------
173nctnvn45cu select count(*) from dual where dummy = to_char(5)                1          1          1             0
6fb6af6nhtby1 select count(*) from dual where dummy = to_char(4)                1          1          1             0
3f2sqh4zrpydb select count(*) from dual where dummy = to_char(1)                1          1          1             0
b8v7fvmqny4u7 select count(*) from dual where dummy = to_char(3)                1          1          1             0
250paq2dcuvvj select count(*) from dual where dummy = to_char(2)                1          1          1             0
1g97h5aq5byqj declare  v_cnt number; begin  for i in 1..5 loop   exec           1          1          1             0
              ute immediate 'select count(*) from dual where dummy =
              to_char('||i||')' into v_cnt;  end loop; end;

6 rows selected.
  • i 값에 의해 하드 파싱이 각각 일어남

Dynamic SQL

hr 세션 2개 접속

SYS@ora19c> select sid, event, wait_class, wait_time, seconds_in_wait, state from v$session_wait where sid in (select sid from v$session where username = 'HR');

       SID EVENT                                    WAIT_CLASS            WAIT_TIME SECONDS_IN_WAIT STATE
---------- ---------------------------------------- -------------------- ---------- --------------- -------------------
        40 SQL*Net message from client              Idle                          0              40 WAITING
       163 SQL*Net message from client              Idle                          0              37 WAITING

세션 1, 2에서 아래 익명 블록 동시 수행

HR@ora19c> declare
        v_cnt number;
begin
        for i in 1..100000 loop
                execute immediate 'select count(*) from dual where dummy = to_char('||i||')' into v_cnt;
        end loop;
end;
/  2    3    4    5    6    7    8

세션 대기 이벤트 조회

SYS@ora19c> /

       SID EVENT                                    WAIT_CLASS            WAIT_TIME SECONDS_IN_WAIT STATE
---------- ---------------------------------------- -------------------- ---------- --------------- -------------------
        40 latch: shared pool                       Concurrency                  -1               0 WAITED SHORT TIME
       163 latch: shared pool                       Concurrency                   0               0 WAITING

SYS@ora19c> /

       SID EVENT                                    WAIT_CLASS            WAIT_TIME SECONDS_IN_WAIT STATE
---------- ---------------------------------------- -------------------- ---------- --------------- -------------------
        40 latch: shared pool                       Concurrency                   0               0 WAITING
       163 latch: shared pool                       Concurrency                   0               0 WAITING

SYS@ora19c> /

       SID EVENT                                    WAIT_CLASS            WAIT_TIME SECONDS_IN_WAIT STATE
---------- ---------------------------------------- -------------------- ---------- --------------- -------------------
        40 latch: shared pool                       Concurrency                  -1               0 WAITED SHORT TIME
       163 library cache: bucket mutex X            Concurrency                   0               0 WAITING

SYS@ora19c> /

       SID EVENT                                    WAIT_CLASS            WAIT_TIME SECONDS_IN_WAIT STATE
---------- ---------------------------------------- -------------------- ---------- --------------- -------------------
        40 latch: shared pool                       Concurrency                  -1               0 WAITED SHORT TIME
       163 latch: shared pool                       Concurrency                   1               0 WAITED KNOWN TIME

SYS@ora19c> /

       SID EVENT                                    WAIT_CLASS            WAIT_TIME SECONDS_IN_WAIT STATE
---------- ---------------------------------------- -------------------- ---------- --------------- -------------------
        40 library cache: mutex X                   Concurrency                  -1               0 WAITED SHORT TIME
       163 library cache: bucket mutex X            Concurrency                   0               0 WAITING

SYS@ora19c> /

       SID EVENT                                    WAIT_CLASS            WAIT_TIME SECONDS_IN_WAIT STATE
---------- ---------------------------------------- -------------------- ---------- --------------- -------------------
        40 latch: shared pool                       Concurrency                  -1               0 WAITED SHORT TIME
       163 latch: shared pool                       Concurrency                   0               0 WAITING

SYS@ora19c> /

       SID EVENT                                    WAIT_CLASS            WAIT_TIME SECONDS_IN_WAIT STATE
---------- ---------------------------------------- -------------------- ---------- --------------- -------------------
        40 row cache mutex                          Concurrency                   0               0 WAITING
       163 latch: shared pool                       Concurrency                   0               0 WAITING

SYS@ora19c> /

       SID EVENT                                    WAIT_CLASS            WAIT_TIME SECONDS_IN_WAIT STATE
---------- ---------------------------------------- -------------------- ---------- --------------- -------------------
        40 latch: shared pool                       Concurrency                  -1               0 WAITED SHORT TIME
       163 latch: shared pool                       Concurrency                   0               0 WAITING

SYS@ora19c> /

       SID EVENT                                    WAIT_CLASS            WAIT_TIME SECONDS_IN_WAIT STATE
---------- ---------------------------------------- -------------------- ---------- --------------- -------------------
        40 latch: shared pool                       Concurrency                   0               0 WAITING
       163 latch: shared pool                       Concurrency                   1               0 WAITED KNOWN TIME

SYS@ora19c> /

       SID EVENT                                    WAIT_CLASS            WAIT_TIME SECONDS_IN_WAIT STATE
---------- ---------------------------------------- -------------------- ---------- --------------- -------------------
        40 latch: shared pool                       Concurrency                  -1               0 WAITED SHORT TIME
       163 latch: shared pool                       Concurrency                  -1               0 WAITED SHORT TIME

SYS@ora19c> /

       SID EVENT                                    WAIT_CLASS            WAIT_TIME SECONDS_IN_WAIT STATE
---------- ---------------------------------------- -------------------- ---------- --------------- -------------------
        40 latch: shared pool                       Concurrency                   0               0 WAITING
       163 latch: shared pool                       Concurrency                   0               0 WAITING

SYS@ora19c> /

       SID EVENT                                    WAIT_CLASS            WAIT_TIME SECONDS_IN_WAIT STATE
---------- ---------------------------------------- -------------------- ---------- --------------- -------------------
        40 latch: shared pool                       Concurrency                  -1               0 WAITED SHORT TIME
       163 latch: shared pool                       Concurrency                  -1               0 WAITED SHORT TIME

SYS@ora19c> /

       SID EVENT                                    WAIT_CLASS            WAIT_TIME SECONDS_IN_WAIT STATE
---------- ---------------------------------------- -------------------- ---------- --------------- -------------------
        40 latch: shared pool                       Concurrency                   0               0 WAITING
       163 latch: shared pool                       Concurrency                   0               0 WAITING

SYS@ora19c> /

       SID EVENT                                    WAIT_CLASS            WAIT_TIME SECONDS_IN_WAIT STATE
---------- ---------------------------------------- -------------------- ---------- --------------- -------------------
        40 SQL*Net message from client              Idle                          0               3 WAITING
       163 SQL*Net message from client              Idle                          0               1 WAITING

SYS@ora19c> select sid, event, total_waits, time_waited from v$session_event where sid in (select sid from v$session where username = 'HR');

       SID EVENT                                    TOTAL_WAITS TIME_WAITED
---------- ---------------------------------------- ----------- -----------
        40 Disk file operations I/O                           1           0
        40 db file sequential read                           17           1
        40 db file scattered read                             4           0
        40 row cache mutex                                   67         193
        40 row cache lock                                    98           4
        40 row cache read                                     2           0
        40 cursor: pin S wait on X                           61         175
        40 latch: shared pool                             16847         484
        40 library cache lock                                 4           0
        40 library cache load lock                            5           0
        40 library cache: mutex X                           144         792
        40 library cache: bucket mutex X                     18          48
        40 library cache: dependency mutex X                  3           1
        40 SQL*Net message to client                          9           0
        40 SQL*Net message from client                        8        6792
        40 events in waitclass Other                         60           5
       163 log file sync                                      1           1
       163 row cache mutex                                   58         250
       163 row cache lock                                   107           4
       163 row cache read                                     2           0
       163 cursor: pin S                                      1           0
       163 cursor: pin S wait on X                           64          95
       163 latch: shared pool                             17298         351
       163 library cache lock                                 6           1
       163 library cache load lock                            2           0
       163 library cache: mutex X                           143         872
       163 library cache: bucket mutex X                     20          75
       163 library cache: dependency mutex X                  1           0
       163 SQL*Net message to client                          9           0
       163 SQL*Net message from client                        8        6549
       163 events in waitclass Other                         46          47

31 rows selected.
  • latch: shard pool : Shared Pool 할당 경합
  • cursor: pin S wait on X : 실행하려는 Cursor가 재작성 중

같은 실행 계획을 사용하는데 각각 생성된 커서 조회

SYS@ora19c> select plan_hash_value, count(*)
from v$sql
group by plan_hash_value
having count(*) > 100;

PLAN_HASH_VALUE   COUNT(*)
--------------- ----------
     2522405774        611

SYS@ora19c> select sql_text, parsing_schema_name from v$sql where plan_hash_value = 2522405774 and rownum = 1;

SQL_TEXT                                                PARSING_SCHEMA_NAME
------------------------------------------------------- --------------------
select count(*) from dual where dummy = to_char(97891)  HR
  • parsing_schema_name 이 보통 업무 팀
  • 과도한 하드 파싱을 일으키고 있는 업무 팀을 찾아서 쿼리 변경 요청

Static SQL

# shared pool flush
SYS@ora19c> alter system flush shared_pool;

System altered.

# session cache cursor 수 0개로 설정
SYS@ora19c> alter session set session_cached_cursors = 0;

Session altered.

세션 1과 세션 2에서 아래 익명 블록 동시 수행

HR@ora19c> declare
        v_cnt number;
begin
        for i in 1..100000 loop
                select count(*) into v_cnt from dual where dummy = to_char(i);
        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');

       SID EVENT                                    TOTAL_WAITS TIME_WAITED
---------- ---------------------------------------- ----------- -----------
        40 log file sync                                      1           1
        40 cursor: pin S                                      1           0
        40 SQL*Net message to client                         10           0
        40 SQL*Net message from client                        9        9480
        40 SQL*Net break/reset to client                      2           0
        40 events in waitclass Other                         13           0
       163 Disk file operations I/O                           3           0
       163 log file sync                                      1           0
       163 cursor: pin S                                      1          40
       163 SQL*Net message to client                         10           0
       163 SQL*Net message from client                        9       12032
       163 SQL*Net break/reset to client                      2           0
       163 events in waitclass Other                         41           0

13 rows selected.
  • exclusive 경합 발생 X

SQL 수행 정보 조회

SYS@ora19c> select sql_id, sql_text, parse_calls, loads, executions, hash_value, plan_hash_value
from v$sql
where sql_text like '%select count(*) into v_cnt from dual%'
and sql_text not like '%v$sql%';  2    3    4

SQL_ID        SQL_TEXT                                                PARSE_CALLS      LOADS EXECUTIONS HASH_VALUE PLAN_HASH_VALUE
------------- ------------------------------------------------------- ----------- ---------- ---------- ---------- ---------------
9m4qjxpjrvz0j declare  v_cnt number; begin  for i in 1..100000 loop             2          1          2 1669200913   0
               select count(*) into v_cnt from dual where dummy = to_
              char(i);  end loop; end;
  • 하드 파싱은 한 번만 일어남

세션 커서

  • 오라클은 한 세션 내에서 세번 이상 수행된 SQL 커서들의 Library Cahce 내에서의 위치와 SQL 텍스트를 PGA 영역에 저장
  • 저장하는 SQL 커서의 개수는 session_cached_cursors 파라미터에 의해 결정됨
  • 이 기능을 사용하면 바로 LCO 위치를 찾아가게 되므로 mutex 점유 시간을 줄일 수 있음
SYS@ora19c> show parameter session_cached_cursors

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
session_cached_cursors               integer     50

실습

SYS@ora19c> alter system flush shared_pool;

System altered.

세션 1, 2 동시 수행

HR@ora19c> declare
        v_cnt number;
begin
        for i in 1..100000 loop
                select count(*) into v_cnt from dual where dummy = to_char(i);
        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');

       SID EVENT                                    TOTAL_WAITS TIME_WAITED
---------- ---------------------------------------- ----------- -----------
        40 log file sync                                      1           1
        40 cursor: pin S                                      6           4
        40 SQL*Net message to client                          9           0
        40 SQL*Net message from client                        8        5627
        40 events in waitclass Other                         31           0
        44 log file sync                                      1           1
        44 cursor: pin S                                      1           0
        44 SQL*Net message to client                          9           0
        44 SQL*Net message from client                        8        4937
        44 events in waitclass Other                         11           0

10 rows selected.

SQL 수행 정보 조회

SYS@ora19c> select sql_id, sql_text, parse_calls, loads, executions, hash_value, plan_hash_value
from v$sql
where sql_text like '%select count(*) into v_cnt from dual%'
and sql_text not like '%v$sql%';  2    3    4

SQL_ID        SQL_TEXT                                                PARSE_CALLS      LOADS EXECUTIONS HASH_VALUE PLAN_HASH_VALUE
------------- ------------------------------------------------------- ----------- ---------- ---------- ---------- ---------------
9fwmdg8qx0vyq declare         v_cnt number; begin         for i in 1.           2          1          2  768634838   0
              .100000 loop                 select count(*) into v_cnt
               from dual where dummy = to_char(i);         end loop;
              end

version count

sql은 같지만 소유자가 다른 경우

hr과 insa 스키마에 동일한 테이블 생성

drop table hr.emp purge;
drop table insa.emp purge;
create table hr.emp tablespace users as select * from hr.employees;
create table insa.emp tablespace users as select * from hr.employees;

동일한 쿼리 수행

HR@ora19c> select * from emp where employee_id = 100;
INSA@ora19c> select * from emp where employee_id = 100;

SQL 수행 정보 확인 → version_count = 2

SYS@ora19c> select sql_id, sql_text, version_count
from v$sqlarea
where sql_text like '%select * from emp where employee_id = 100%'
and sql_text not like '%v$sqlarea%';  2    3    4

SQL_ID        SQL_TEXT                                                VERSION_COUNT
------------- ------------------------------------------------------- -------------
0t028xxgcphg0 select * from emp where employee_id = 100                           2
  • child cursor가 2개 생성됨

child cursor가 생성된 이유 조회

select * from v$sql_shared_cursor where sql_id = '0t028xxgcphg0';
select sql_id, child_number, auth_check_mismatch, translation_mismatch from v$sql_shared_cursor where sql_id = '0t028xxgcphg0';

실행 계획

SYS@ora19c> select * from table(dbms_xplan.display_cursor('0t028xxgcphg0', 0));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  0t028xxgcphg0, child number 0
-------------------------------------
select * from emp where employee_id = 100

Plan hash value: 3956160932

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |       |       |     3 (100)|          |
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |    69 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("EMPLOYEE_ID"=100)

18 rows selected.

SYS@ora19c> select * from table(dbms_xplan.display_cursor('0t028xxgcphg0', 1));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  0t028xxgcphg0, child number 1
-------------------------------------
select * from emp where employee_id = 100

Plan hash value: 3956160932

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |       |       |     3 (100)|          |
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |    69 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("EMPLOYEE_ID"=100)

18 rows selected.
  • 쿼리 문장은 같지만 소유자가 다르므로 실행 계획이 다르게 생성되어야 함 → parent cursor + 소유자마다 child cursor가 각각 생김 ⇒ cursor 3개 생성

varchar2 size(32, 128, 2000, 4000) 4가지 크기로 결정

HR@ora19c> var name varchar2(10)
HR@ora19c> exec :name := 'King'

PL/SQL procedure successfully completed.

HR@ora19c> print name

NAME
--------------------------------------------------
King

HR@ora19c> select last_name, salary from hr.employees where last_name = :name;

LAST_NAME                     SALARY
------------------------- ----------
King                           10000
King                           24000

HR@ora19c> var name varchar2(1000)
HR@ora19c> exec :name := 'Grant'

PL/SQL procedure successfully completed.

HR@ora19c> select last_name, salary from hr.employees where last_name = :name;

LAST_NAME                     SALARY
------------------------- ----------
Grant                           2600
Grant                           7000
SYS@ora19c> select sql_id, sql_text, version_count
from v$sqlarea
where sql_text like '%hr.employees%'
and sql_text not like '%v$sqlarea%';

SQL_ID        SQL_TEXT                                                VERSION_COUNT
------------- ------------------------------------------------------- -------------
gqgwd5rvu5ftu select last_name, salary from hr.employees where last_n             2
              ame = :name
  • 바인드 변수를 두번 선언하면서 크기를 다르게 설정
  • child cursor가 2개 생성됨

child cursor가 생성된 이유 조회

  • v$sql_shared_cursor를 보고 child cursor가 생성된 이유를 찾아야 함
select * from v$sql_shared_cursor where sql_id = 'gqgwd5rvu5ftu';

바인드 변수 정보 조회

select *
from v$sql_bind_capture
where sql_id = 'gqgwd5rvu5ftu';

실행 계획

SYS@ora19c> select * from table(dbms_xplan.display_cursor('gqgwd5rvu5ftu', 0));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  gqgwd5rvu5ftu, child number 0
-------------------------------------
select last_name, salary from hr.employees where last_name = :name

Plan hash value: 1600171752

---------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |             |       |       |     2 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| EMPLOYEES   |     1 |    12 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN                  | EMP_NAME_IX |     1 |       |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("LAST_NAME"=:NAME)

19 rows selected.

SYS@ora19c> select * from table(dbms_xplan.display_cursor('gqgwd5rvu5ftu', 1));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  gqgwd5rvu5ftu, child number 1
-------------------------------------
select last_name, salary from hr.employees where last_name = :name

Plan hash value: 1600171752

---------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |             |       |       |     2 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| EMPLOYEES   |     1 |    12 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN                  | EMP_NAME_IX |     1 |       |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("LAST_NAME"=:NAME)

19 rows selected.
  • child cursor의 실행 계획이 모두 동일

특정 cursor를 purge(11g)

SYS@ora19c> select sql_id, sql_text, version_count, address, hash_value
from v$sqlarea
where sql_text like '%hr.employees%'
and sql_text not like '%v$sqlarea%';  2    3    4

SQL_ID        SQL_TEXT                                                VERSION_COUNT ADDRESS          HASH_VALUE
------------- ------------------------------------------------------- ------------- ---------------- ----------
gqgwd5rvu5ftu select last_name, salary from hr.employees where last_n             2 0000000069B92568 4154637114
              ame = :name

SYS@ora19c> exec dbms_shared_pool.purge('0000000069B92568,4154637114', 'c');

PL/SQL procedure successfully completed.

SYS@ora19c> select sql_id, sql_text, version_count, address, hash_value
from v$sqlarea
where sql_text like '%hr.employees%'
and sql_text not like '%v$sqlarea%';  3    4

no rows selected

과도한 하드 파싱 문제점

  • 실행 계획 생성 시에 과도한 CPU, 메모리 사용
  • Library Cache Chain 확장으로 인한 검색 시간 증가, mutex 점유 시간 증가 → soft parsing 성능 저하
  • shared pool fragmentation(단편화) : free chunk가 작은 크기로 쪼개져서 chunk 수가 증가하는 현상 → 체인의 길이가 길어져 검색 속도 저하 유발, 내가 필요한 free chunk를 찾지 못해서 ORA-04031 오류 발생 확률이 높아짐

row cache lock

  • data dictionary cache(row cache) 는 오라클 딕셔너리 정보에 대한 캐시 영역
    • 유저, 객체, 테이블, 세그먼트, 컬럼, 인덱스, 시퀀스, 뷰, 프로시저, 함수, 패키지, 트리거, …
  • row cache lock은 딕셔너리 테이블(객체)을 보호하는 시스템 lock
  • DDL, DCL 작업을 수행하면 딕셔너리 정보에 대한 입력, 수정, 삭제 발생 → row cache lock 발생
  • 운영 환경에서 DDL, DCL은 잘 안 하기 때문에 보통은 문제 안됨
  • 시퀀스 사용 시 캐시 옵션을 사용하지 않으면 row cache lock에 의한 경합이 심할 수 있음
    • 시퀀스를 생성할 때는 캐시 옵션을 통해 미리 다음 시퀀스 번호를 여러 개 생성해두고 사용
SYS@ora19c> select pool, name, bytes from v$sgastat where name = 'row cache';

POOL           NAME                                                    BYTES
-------------- -------------------------------------------------- ----------
shared pool    row cache                                               25864
SYS@ora19c> select cache#, type, parameter from v$rowcache;

    CACHE# TYPE        PARAMETER
---------- ----------- --------------------------------
         3 PARENT      dc_rollback_segments
         1 PARENT      dc_free_extents
         4 PARENT      dc_used_extents
         2 PARENT      dc_segments
         0 PARENT      dc_tablespaces
         5 PARENT      dc_tablespace_quotas
         6 PARENT      dc_files
        10 PARENT      dc_users
         8 PARENT      dc_objects
        17 PARENT      dc_global_oids
        12 PARENT      dc_constraints
        13 PARENT      dc_sequences
        16 PARENT      dc_histogram_defs
        54 PARENT      dc_sql_prs_errors
        32 PARENT      kqlsubheap_object
        19 PARENT      dc_table_scns
        18 PARENT      dc_outlines
        15 PARENT      dc_props
        60 PARENT      dc_cdbprops
        14 PARENT      dc_profiles
        47 PARENT      realm cache
        48 PARENT      Command rule cache
        49 PARENT      Realm Object cache
        46 PARENT      Rule Set Cache
        55 PARENT      DV Auth Cache
        34 PARENT      extensible security principal in
        33 PARENT      Unused
        36 PARENT      Unused
        37 PARENT      Unused
        38 PARENT      XS security class privilege
        39 PARENT      extensible security midtier cach
        43 PARENT      AV row cache 1
        44 PARENT      AV row cache 2
        45 PARENT      AV row cache 3
        35 PARENT      triton security name to ID
        61 PARENT      dc_statistics_status
        62 PARENT      dc_realtime_colst
        63 PARENT      dc_realtime_tabst
        20 PARENT      rule_info
        21 PARENT      rule_or_piece
        64 PARENT      key_shard
        23 PARENT      dc_qmc_ldap_cache_entries
        52 PARENT      qmc_app_cache_entries
        53 PARENT      qmc_app_cache_entries
        27 PARENT      qmtmrcin_cache_entries
        28 PARENT      qmtmrctn_cache_entries
        29 PARENT      qmtmrcip_cache_entries
        30 PARENT      qmtmrctp_cache_entries
        31 PARENT      qmtmrciq_cache_entries
        26 PARENT      qmtmrctq_cache_entries
         9 PARENT      qmrc_cache_entries
        50 PARENT      qmemod_cache_entries
        24 PARENT      outstanding_alerts
        22 PARENT      dc_awr_control
        25 PARENT      SMO rowcache
        40 PARENT      sch_lj_objs
        41 PARENT      sch_lj_oids
        56 PARENT      dc_cdbfiles
        57 PARENT      dc_cdbservices
        58 PARENT      dc_pdbdba
        59 PARENT      dc_pdbstates
         7 SUBORDINATE dc_users
         8 SUBORDINATE dc_object_grants
        16 SUBORDINATE dc_histogram_data
        16 SUBORDINATE dc_histogram_data
        19 SUBORDINATE dc_partition_scns
         7 SUBORDINATE dc_users
         7 SUBORDINATE dc_users
        47 SUBORDINATE realm auth
        47 SUBORDINATE realm auth
        49 SUBORDINATE Realm Subordinate Cache
         7 SUBORDINATE dc_users
         7 SUBORDINATE dc_users
        21 SUBORDINATE rule_fast_operators
         7 SUBORDINATE dc_users

75 rows selected.

시퀀스 사용 시 row cache lock 확인

# 시퀀스 생성
HR@ora19c> create sequence hr.seq_1 nocache;

Sequence created.

# 시퀀스 정보 조회
SYS@ora19c> col sequence_owner format a10
SYS@ora19c> col sequence_name format a20
SYS@ora19c> select * from dba_sequences where sequence_owner = 'HR' and sequence_name = 'SEQ_1';

SEQUENCE_O SEQUENCE_NAME         MIN_VALUE  MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER S E S S K
---------- -------------------- ---------- ---------- ------------ - - ---------- ----------- - - - - -
HR         SEQ_1                         1 1.0000E+28            1 N N          0           1 N N N N N
  • c : cycle_flag

세션 1, 2가 동시에 수행

HR@ora19c> declare
        v_value number;
begin
        for i in 1..100000 loop
                select hr.seq_1.nextval into v_value from dual;
        end loop;
end;
/  2    3    4    5    6    7    8

PL/SQL procedure successfully completed.

row cache lock 조회

SYS@ora19c> select h.address, h.saddr, s.sid, h.lock_mode
from v$rowcache_parent h, v$rowcache_parent w, v$session s
where h.address = w.address
and w.saddr = (select saddr from v$session where event = 'row cache lock' and rownum = 1)
and h.saddr = s.saddr
and h.lock_mode > 0;  2    3    4    5    6

no rows selected

SYS@ora19c> /

no rows selected

SYS@ora19c> /

ADDRESS          SADDR                   SID  LOCK_MODE
---------------- ---------------- ---------- ----------
000000006933C100 0000000074133F48         44          5

SYS@ora19c> /

ADDRESS          SADDR                   SID  LOCK_MODE
---------------- ---------------- ---------- ----------
000000006933C100 000000007425D000        163          5

SYS@ora19c> /

ADDRESS          SADDR                   SID  LOCK_MODE
---------------- ---------------- ---------- ----------
000000006933C100 0000000074133F48         44          5

SYS@ora19c> /

ADDRESS          SADDR                   SID  LOCK_MODE
---------------- ---------------- ---------- ----------
000000006933C100 0000000074133F48         44          5

SYS@ora19c> /

ADDRESS          SADDR                   SID  LOCK_MODE
---------------- ---------------- ---------- ----------
000000006933C100 000000007425D000        163          5

SYS@ora19c> /

ADDRESS          SADDR                   SID  LOCK_MODE
---------------- ---------------- ---------- ----------
000000006933C100 0000000074133F48         44          5

SYS@ora19c> /

no rows selected

누적 대기 이벤트 조회

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
---------- ---------------------------------------- ----------- -----------
       163 Disk file operations I/O                           1           0
       163 log file switch completion                         4           4
       163 log file sync                                      3           1
       163 db file sequential read                            3           0
       163 db file scattered read                           280          17
       163 db file parallel read                             54           0
       163 row cache mutex                                   16          22
       ****163 row cache lock                                 75214        1052
       163 library cache: mutex X                             6           6
       163 SQL*Net message to client                         10           0
       163 SQL*Net message from client                        9       13838
       163 events in waitclass Other                         16           1
        44 Disk file operations I/O                           1           0
        44 log file switch completion                         1           2
        44 log file sync                                      3           2
        44 db file sequential read                            3           0
        44 db file scattered read                           263          17
        44 db file parallel read                             37           0
        44 row cache mutex                                   12          18
        44 row cache lock                                 75227        1061
        44 cursor: pin S                                      2           0
        44 library cache: mutex X                            12          14
        44 SQL*Net message to client                         10           0
        44 SQL*Net message from client                        9       13384
        44 events in waitclass Other                         18           1

25 rows selected.

추적

# sid로 SQL Address 찾기
SYS@ora19c> select prev_sql_addr from v$session where sid = 163;

PREV_SQL_ADDR
----------------
00000000621B03A0

# sql address로 SQL 문장 찾기
SYS@ora19c> select sql_text from v$sql where address = (select prev_sql_addr from v$session where sid = 163);

SQL_TEXT
-------------------------------------------------------
declare  v_value number; begin  for i in 1..100000 loop
   select hr.seq_1.nextval into v_value from dual;  end
 loop; end;

# 시퀀스 정보 조회 -> 캐시 설정 안됨 
SYS@ora19c> select * from dba_sequences where sequence_owner = 'HR' and sequence_name = 'SEQ_1';

SEQUENCE_O SEQUENCE_NAME         MIN_VALUE  MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER S E S S K
---------- -------------------- ---------- ---------- ------------ - - ---------- ----------- - - - - -
HR         SEQ_1                         1 1.0000E+28            1 N N          0      220001 N N N N N
  • row cache lock 대기 이벤트가 발생된 원인은 sequence nocache 속성으로 인해 발생

해결방안

  • cache 속성으로 수정해야 함
SYS@ora19c> alter sequence hr.seq_1 cache 20;

Sequence altered.

SYS@ora19c> select * from dba_sequences where sequence_owner = 'HR' and sequence_name = 'SEQ_1';

SEQUENCE_O SEQUENCE_NAME         MIN_VALUE  MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER S E S S K
---------- -------------------- ---------- ---------- ------------ - - ---------- ----------- - - - - -
HR         SEQ_1                         1 1.0000E+28            1 N N         20      220001 N N N N N
  • cache size를 20으로 설정

세션 1, 2에서 시퀀스 동시 사용

HR@ora19c> declare
        v_value number;
begin
        for i in 1..100000 loop
                select hr.seq_1.nextval into v_value from dual;
        end loop;
end;
/   2    3    4    5    6    7    8

PL/SQL procedure successfully completed.

row cache lock 조회

SYS@ora19c> select h.address, h.saddr, s.sid, h.lock_mode
from v$rowcache_parent h, v$rowcache_parent w, v$session s
where h.address = w.address
and w.saddr = (select saddr from v$session where event = 'row cache lock' and rownum = 1)
and h.saddr = s.saddr
and h.lock_mode > 0;  2    3    4    5    6

no rows selected

SYS@ora19c> /

no rows selected

SYS@ora19c> /

no rows selected

SYS@ora19c> /

no rows selected

누적 대기 이벤트 조회

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
---------- ---------------------------------------- ----------- -----------
       163 Disk file operations I/O                           1           0
       163 log file sync                                      2           1
       163 db file scattered read                            11           1
       163 enq: SQ - contention                            4600         155
       163 cursor: pin S                                      1           0
       163 library cache: mutex X                            14          13
       163 SQL*Net message to client                          9           0
       163 SQL*Net message from client                        8        4624
       163 events in waitclass Other                         19           1
        44 Disk file operations I/O                           1           0
        44 log file sync                                      2           1
        44 db file scattered read                            14           1
        44 enq: SQ - contention                            4618         188
        44 cursor: pin S                                      3           1
        44 library cache: mutex X                            13          13
        44 SQL*Net message to client                          9           0
        44 SQL*Net message from client                        8        4857
        44 events in waitclass Other                         23           2

18 rows selected.
  • enq: SQ - contention : 시퀀스 캐시 크기가 작아서 발생

해결 방안

  • cache 크기 설정을 크게 해줘야 함
SYS@ora19c> alter sequence hr.seq_1 cache 100;

Sequence altered.

SYS@ora19c> select * from dba_sequences where sequence_owner = 'HR' and sequence_name = 'SEQ_1';

SEQUENCE_O SEQUENCE_NAME         MIN_VALUE  MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER S E S S K
---------- -------------------- ---------- ---------- ------------ - - ---------- ----------- - - - - -
HR         SEQ_1                         1 1.0000E+28            1 N N        100      420001 N N N N N
  • 시퀀스 캐시 크기를 100으로 설정

세션 1, 2에서 시퀀스 동시 사용

HR@ora19c> declare
  2          v_value number;
begin
        for i in 1..100000 loop
                select hr.seq_1.nextval into v_value from dual;
        end loop;
end;
/   3    4    5    6    7    8

PL/SQL procedure successfully completed.

누적 대기 이벤트 조회

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
---------- ---------------------------------------- ----------- -----------
       163 Disk file operations I/O                           1           0
       163 log file sync                                      2           1
       163 db file scattered read                             3           0
       163 enq: SQ - contention                             212          11
       163 cursor: pin S                                      1           1
       163 library cache: mutex X                             5           5
       163 SQL*Net message to client                          9           0
       163 SQL*Net message from client                        8        4097
       163 events in waitclass Other                         12           0
        44 Disk file operations I/O                           1           0
        44 log file sync                                      2           0
        44 db file scattered read                             2           0
        44 enq: SQ - contention                             203          20
        44 cursor: pin S                                      2           1
        44 library cache: mutex X                            10          10
        44 SQL*Net message to client                          9           0
        44 SQL*Net message from client                        8        4368
        44 events in waitclass Other                         17           1

18 rows selected.
  • enq: SQ - contention 대기 시간이 줄어 들음