1. 전체적인 lock 대기 상황 모니터링 쿼리

select l.session_id SID ,(case when lock_type = 'Transaction' then 'TX' when lock_type = 'DML' then 'TM' end) TYPE , mode_held , mode_requested mode_reqd ,(case when lock_type = 'Transaction' then to_char(trunc(lock_id1/power(2,16))) when lock_type = 'DML' then (select object_name from dba_objects where object_id = l.lock_id1) end) "USN/Table" ,(case when lock_type = 'Transaction' then bitand(lock_id1, to_number('ffff', 'xxxx')) + 0 end) "SLOT" ,(case when lock_type = 'Transaction' then to_number(lock_id2) end) "SQN" ,(case when blocking_others = 'Blocking' then ' <<<<<' end) Blocking from dba_lock l where lock_type in ('Transaction', 'DML' ) order by session_id, lock_type, lock_id1, lock_id2

2. 현재 유저의 lock 상태 조회쿼리

select username, v$lock.sid, id1, id2 , lmode, request, block, v$lock.type from v$lock, v$session where v$lock.sid = v$session.sid and v$session.username = USER



1.  불필요하게 커멋을 자주 수행하지 않는다.


2.  fetch across commit 형태의 프로그램 작성을 피해 다른 방식으로 구현한다. ANSI

표준에 따르면 커맛 이전에 열려 있던 커서는 더는 Fetch 하면 안 된다. 다른 방식으

로 구현하기 어렵다면 커빗 횟수를 줄여본다.


3.  트랜잭션이 몰리는 시간대에 오래 걸리는 쿼리가 같이 수행되지 않도록 시간을 조정

한다.


4. 큰 테이블을 일정 범위로 나누어 읽고 단계적으로 실행할 수 있도록 코딩한다.

Snapshot too old 발생 기능성을 줄일 뿐 아니라 문제가 발생했을 때 특정 부분부

터 다시 시작할 수도 있어 유리하다. 물론 그렇게 해도 읽기 일관성에 문제가 없을

때에만적용해야한다



5. 오랜 시간에 걸쳐 같은 블록을 여러 번 방문하는 Nested Loop 형태의 조인문 또는

인텍스를 경유한 테이블 액세스를 수반하는 프로그램이 있는지 체크하고, 이를 회피

할 수 있는 방법(조인 메소드 변경, F비I Table Scan 등)을 찾는다.



6. 소트 부하를 감수하더라도 order by 등을 강제로 삽입해 소트연산이 발생하도록 한

다. 많은 데이터를 오랜 시간에 걸쳐 Fetch 하는 동안 Undo 정보를 지속적으로 참

조하기 때문에 문제가 발생하는 것이므로, 서버 내에서 빠르게 데이터를 읽어 Temp

세그먼트에 저장하는 데에만 성공하면 이후에는 같은 블록을 아무리 재방문하더라

도 더는 에러가 발생할까 걱정하지 않아도 된다.


7. 만약 delayed 블록 클린아웃에 의해 Snapshot too old가 발생하는 것으로 의심되면

대량 업데이트 후에 곧바로 해당 테이블에 대해 Full Scan 하도록 쿼리를 날리는 것

도 하나의 해결방법이 될 수 있다


sel ect 1*+ ful l(t) *1 count(* ) from table name t


oracle data를 sqlplus를 통해서 download 하는 script 

getdata.zip


세션 커서에서 커서를 찾은 비율, 즉 세션 커서 캐시 히트율(Hit Ratio) 을 구하는 쿼리


1. 쿼리

select a.value "session cursor cache hits"

                   , b.value "total parse call count"

                  , round (a.value/b.value* 100, 2) "session cursor cache hits%"

          from v$sysstat a, v$sysstat b

          where a.name = 'session cursor cache hits'

         and b.name = 'parse count (total)'



2. 결과

session cursor cache hits total parse call count session cursor cache hits%

------------------------- ---------------------- --------------------------

                    88745                 115342                      76.94

1. 쿼리

SQL> set linesize 300

SQL> column TABLE_NAME format a30

SQL> column COMMENTS   format a30

SQL> select * from dict where table_name like 'DBA_HIST_SQL%';


2.결과

TABLE_NAME                     COMMENTS

------------------------------ ------------------------------

DBA_HIST_SQLBIND               SQL Bind Information

DBA_HIST_SQLCOMMAND_NAME       Sql command types

DBA_HIST_SQLSTAT               SQL Historical Statistics Info

                               rmation


DBA_HIST_SQLTEXT               SQL Text

DBA_HIST_SQL_BIND_METADATA     SQL Bind Metadata Information

DBA_HIST_SQL_PLAN              SQL Plan Information

DBA_HIST_SQL_SUMMARY           Summary of SQL Statistics

DBA_HIST_SQL_WORKAREA_HSTGRM   SQL Workarea Histogram History


8 rows selected.


SQL>  select * from dict where table_name like 'DBA_ALL_%';


TABLE_NAME                     COMMENTS

------------------------------ ------------------------------

DBA_ALL_TABLES                 Description of all object and

                               relational tables in the datab

                               ase



SQL> 

v$sql 의 값들은 누적치.

SQL 수행횟수로 나눈 평균값, SQL한번 수행당 얼만만큼의 일량과 시간을 소비하는 지 계산해야 의미 있는 분석이 가능함.



1. 스키마별 쿼리 수행 통계

select parsing_schema_name 

     , count(*) sql_cnt

     , count(distinct substr(sql_text, 1, 100)) sql_cnt2

     , sum(executions) executions

     , round(avg(buffer_gets/executions)) buffer_gets

     , round(avg(disk_reads/executions)) disk_reads

     , round(avg(rows_processed/executions)) rows_processed

     , round(avg(elapsed_time/executions/1000000),2) "ELAPSED_TIME(AVG)"

     , count(case when elapsed_time/executions/1000000 >= 10 then 1 end) "BAD SQL"

     , round(max(elapsed_time/executions/1000000),2) "ELAPSED_TIME(MAX)"

from   v$sql

where  last_active_time >= sysdate - 7

and    executions > 0

group by parsing_schema_name



2. 실행예




3. 개별쿼리별 조회

select 

         sql_id  , child_number , sql_text  , sql_fulltext   , parsing_schema_name      -- (1)

       , sharable_mem    , persistent_mem    , runtime_mem                             --(2)

       , loads    , invalidations    , parse_calls    , executions   , fetches   , rows_processed  --(3)

       , cpu_time   , elapsed_time                                                             -- (4)

       , buffer_gets   , disk_reads   , sorts                                                  -- (5)

       , application_wait_time , concurrency_wait_time                                    -- (6)

       , cluster_wait_time , user_io_wait_time                                               -- (6)

       , first_load_time , last_active_time                                                     --(7)

from v$sql;

1) 라이브러리 캐시에 적재된 SQL 커서 자체에 대한 정보

2) SQL 커서에 의해 사용되는 메모리 사용량

3) 하드파싱 및 무효화 발생횟수, Parse, Execute, Fetch Call 발생 횟수, Execute 또

는 Fetch Call 시점에 처리한 로우 건수 등

4) SQL을 수행하면서 사용된 CPU time과 소요시간(microsecond)

5) SQL을 수행하면서 발생한 논리적 블록 읽기와 디스크 읽기, 그리고 소트 발생 횟수

6) SQL 수행 도중 대기 이벤트 때문에 지연이 발생한 시간(microsecond)

7) 커서가 라이브러리 캐시에 처음 적재된 시점, 가장 마지막에 수행된 시점


$ORA_HOME/network/admin/listener.ora


LISTENER =

  (DESCRIPTION_LIST =

    (DESCRIPTION =

      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))

      (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))

      (ADDRESS = (PROTOCOL = TCP)(HOST = 10.0.2.15)(PORT = 1521))

    )

  )


SID_LIST_LISTENER =

  (SID_LIST =

   (SID_DESC =

      (SID_NAME = PLSExtProc)

      (ORACLE_HOME = /oracle11/product/11.2.0/dbhome_1)

      (PROGRAM = extproc)

   )

   (SID_DESC =

      (GLOBAL_DBNAME = orcl11)

      (ORACLE_HOME = /oracle11/product/11.2.0/dbhome_1 )

      (SID_NAME = orcl11)

    )

  )



ADR_BASE_LISTENER = /oracle11



$ORA_HOME/network/admin/tnsnames.ora


ORCL11 =

  (DESCRIPTION =

    (ADDRESS_LIST =

      (ADDRESS = (PROTOCOL = TCP)(HOST = 10.0.2.15)(PORT = 1521))

      (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))

    )

    (CONNECT_DATA =

      (SERVER = DEDICATED)

      (SERVICE_NAME = orcl11)

    )

  )


LISTENER_ORCL11 =

 (ADDRESS_LIST =

   (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))

   (ADDRESS = (PROTOCOL = TCP)(HOST = 10.0.2.15)(PORT = 1521))

 )



select parsing_schema_name 

     , count(*) sql_cnt

     , count(distinct substr(sql_text, 1, 100)) sql_cnt2

     , sum(executions) executions

     , round(avg(buffer_gets/executions)) buffer_gets

     , round(avg(disk_reads/executions)) disk_reads

     , round(avg(rows_processed/executions)) rows_processed

     , round(avg(elapsed_time/executions/1000000),2) "ELAPSED_TIME(AVG)"

     , count(case when elapsed_time/executions/1000000 >= 10 then 1 end) "BAD SQL"

     , round(max(elapsed_time/executions/1000000),2) "ELAPSED_TIME(MAX)"

from   v$sql

where  last_active_time >= sysdate - 7

and    executions > 0

group by parsing_schema_name

;



AWR과 ASH 를 활용하는 법이다. 자세한 설명은 성능고도화 1편 224page를 참고한다.

사용예이다..














  • 현재 접속해서 활동 중인 Active 세션 정보를 1초에 한번씩 샘플링해서 ASH 버퍼에 저장
  • 접속이 끊기 세션 정보도  저장되어 있으므로  추후 문제 추적이 용이함.
  • 내용은 AWR에 저장됨

select 

  sample_id, sample_time               --(1)

, session_id, session_serial#, user_id, xid  --(2)

, sql_id, sql_child_number, sql_plan_hash_value  --(3)

, session_state    --(4)

, qc_instance_id, qc_session_id  --(5)

, blocking_session, blocking_session_serial#, blocking_session_status  --(6)

, event, event#, seq#, wait_class, wait_time, time_waited  --(7)

, p1text, p1, p2text, p2, p3text, p3  --(8)

, current_obj#, current_file#, current_block#  --(9)

, program, module, action, client_id   --(10)

from   V$ACTIVE_SESSION_HISTORY

where rownum <= 10;




  (1)  샘플링이 일어난 시간과 샘플ID

  (2)  세션정보, User명 , 트랜잭션ID

  (3)  수행중 SQL 정보

  (4)  현재 세션의 상태 정보, 'ON CPU' 또는 'WAITING'

  (5)  병령 Slave 세션일 때, 쿼리 코디네이터(QC) 정보를 찾을 수 있게 함

  (6) 현재 세션 진행을 막고 있는 세션 정보

  (7) 현재 발생중인 대기 이벤트 정보

  (8) 현재 발생중인 대기 이벤트의 파라미터 정보

  (9) 해당 세션이 현재 참조하고 있는 오프젝트 정보, v$session 뷰에 있는 row_wait_obj#, row_wait_file#, row_wait_block# 칼럼을 가져온 것임

  (10) 애플리케이션 정보

  

+ Recent posts