DB/ORACLE

DBMS_APPLICATION_INFO 패키지 사용

적외선 2013. 12. 13. 11:05

DBMS_APPLICATION_INFO 패키지 사용


DBMS_APPLICATION_INFO 패키지는 의미하는 바와 같이, 애플리케이션의 정보를 제공할 수 있게 한다.
DBMS_APPLICATION_INFO 패키지를 통해 설정된 값은 V$SESSION, V$SQLAREA에 조회해 출력할 수도 있고,
패키지내의 제공된 컴포넌트로 출력해 볼 수도 있다.
이에 대한 내용은 아래의 예제를 보면 쉽게 알 수 있으므로, 별도의 설명이 필요없으리라 생각된다.
여기서는 SQL*PLUS상에서 패키지의 사용법에 대해 설명한뒤, PL/SQL, PRO*C에서 사용법을 차례로 설명하겠다.



DBMS_APPLICATION_INFO패키지가 제공하는 Subprogram은 다음과 같다.

set_module(module_name in varchar2, action_name in varchar2)
현재 실행중인 모듈명을 설정
모듈명은 식별하기 용이한 아무이름이나 지정할 수 있다.

set_action
현재 모듈내에서 진행중인 작업명을 설정. 
작업에 맞게 적당한 이름(select중.., update중..)을 아무이름이나 지정하면 된다.

read_module
set_module에서 지정한 모듈명을 읽어옴

set_client_info
세션의 client_info필드를 설정

read_client_info
세션의 client_info필드를 읽어옴

set_session_longops
long operations에 대한 설정인데 여기에 대해선 설명을 따로 하지 않겠다.
필요하면 스스로 알아보기 바란다.


V_SESSION : module, action, client_info
V$SQLAREA : module, action




[예제]
SQL> conn system/manager
Connected.
SQL> @?/rdbms/admin/dbmsutil.sql

SQL> connect kang/xxxxxx
Connected.
SQL> exec dbms_application_info.set_module('dbakorea','test...');

PL/SQL procedure successfully completed.

SQL> col module format a20
SQL> col action format a20
SQL> col client_info format a20
SQL> select module, action, client_info from v$session where module is not null;

MODULE               ACTION               CLIENT_INFO
-------------------- -------------------- --------------------
T.O.A.D.
T.O.A.D.
dbakorea             test...

SQL> exec dbms_application_info.set_action('select member table..');

PL/SQL procedure successfully completed.

SQL> select module, action, client_info from v$session   
  2  where module is not null;

MODULE               ACTION               CLIENT_INFO
-------------------- -------------------- --------------------
T.O.A.D.
T.O.A.D.
dbakorea             select member table.
                     .

SQL> select * from member;

ID         PASS       NAME
---------- ---------- ----------
maddog     1111       강명규
superman   1111       슈퍼맨
dbakorea   1111       강명규

SQL> exec dbms_application_info.set_action('update member table');

PL/SQL procedure successfully completed.

SQL> select module, action, client_info from v$session    
  2  where module is not null;

MODULE               ACTION               CLIENT_INFO
-------------------- -------------------- --------------------
T.O.A.D.
T.O.A.D.
dbakorea             update member table

SQL> update member set name='superman' where name='슈퍼맨';

1 행이 갱신되었습니다.

SQL> commit;

Commit complete.


SQL> col sql_text format a50
SQL> col action format a20
SQL> select sql_text, disk_reads, module, action from v$sqlarea where module='dbakorea';

SQL_TEXT                                           DISK_READS MODULE               ACTION
-------------------------------------------------- ---------- -------------------- --------------------
BEGIN dbms_application_info.set_action('select mem          0 dbakorea             test...
ber table..'); END;

select * from member                                        0 dbakorea             test...
select module, action, client_info from v$session           0 dbakorea             test...
where module is not null

select sql_text, disk_reads, module, action from v          0 dbakorea             update member table
$sqlarea where module='dbakorea'



위에서는 client_info에 대한 설정을 하지 않았는데, 마저 설정하고 다시 v$session을 보자.

SQL> exec dbms_application_info.set_client_info('test.. by myunggyu');

PL/SQL procedure successfully completed.

SQL> select module, action, client_info from v$session where module is not null;

MODULE               ACTION               CLIENT_INFO
-------------------- -------------------- --------------------
T.O.A.D.
T.O.A.D.
dbakorea             update member table  test.. by myunggyu

SQL> 


v$session과 v$sqlarea에서 얻을 수 있는 정보는 dbms_application_info패키지내의
read_module, read_client_info컴포넌트로부터 얻을 수도 있다. 
그럼, session과 v$sqlarea대신 read_module, read_client_info를 이용해 출력해 보겠다.

SQL> set serveroutput on
SQL> var module_name varchar2(48)
SQL> var action_name varchar2(32)
SQL> var client_info varchar2(64)
SQL> exec dbms_application_info.read_module(:module_name, :action_name);

PL/SQL procedure successfully completed.

SQL> print module_name

MODULE_NAME
--------------------------------------------------------------------------------------------------------------------------------
dbakorea

SQL> print action_name

ACTION_NAME
--------------------------------
update member table

SQL> exec dbms_application_info.read_client_info(:client_info);

PL/SQL procedure successfully completed.

SQL> print client_info 

CLIENT_INFO
--------------------
test.. by myunggyu



[적용사례]
SQL*PLUS에서 매번 위와 같이 하기 보다는 PL/SQL이나 PRO*C에서 사용하면 유용할 것이다.
오래 걸리는 작업이나 락 걸린 프로세스의 현재 진행과정을 파악하면 어디에서 문제가 되는지 파악하기 용이할 것이다.
아래에 PL/SQL을 이용하는 프로시저의 예를 보였다.


SQL> create or replace procedure add_member(
  2  v_id varchar2,
  3  v_pass varchar2, 
  4  v_name varchar2
  5  )
  6  AS
  7  begin
  8   dbms_application_info.set_module('add_member', 'insert data into member');
  9   insert into member(id, pass, name) values (v_id, v_pass, v_name);
10   dbms_application_info.set_module('','');
11  end;
12  /

Procedure created.

SQL> exec add_member('america', '1111', '깡패');

PL/SQL procedure successfully completed.


위와 같이 했을때 insert 과정에서 오래 걸린다면(그럴리가 거의 없겠지만), v$session과 v$sqlarea를 조회하면
'insert data into member'작업중 hang이 걸린다는 것을 파악할 수 있을 것이다. INSERT가 금방 끝난다면
INSERT후 모듈명,작업명이 둘다 NULL로 변경될 것이다.
음.. 결론을 내리자면, dbms_application_info는 디버그용으로 Oracle trace, SQL trace에서 이용된다고 하겠다.


PRO*C에서는 다음과 같은 방식으로 하면 되겠다.

int connect_DB(char *uid, char *passwd) 

        /* DB서버에 접속 */ 
        EXEC SQL WHENEVER SQLERROR DO sql_error("ORACLE error--\n"); 
        EXEC SQL CONNECT :uid IDENTIFIED BY :passwd; 
        
        EXEC SQL CALL DBMS_APPLICATION_INFO.SET_MODULE('PROC_APP', 'CONNECTED');
        return 1; 


int select_DB(char *id) 

        varchar name[11]; 
        
        EXEC SQL CALL DBMS_APPLICATION_INFO.SET_ACTION('SELECT MEMBER TABLE');
        
        EXEC SQL select name INTO :name from member where id = :id; 
        
        if(sqlca.sqlcode == 1403) 
        { 
                err_print("존재하지 않는 ID: [%s]\n", id); 
                return -1; 
        } 
        else 
        { 
                out_print("[%s] ID를 가진 사람의 이름은 [%.*s]입니다.\n", id, name.len, name.arr); 
                return 1; 
        } 


This article comes from dbakorea.pe.kr (Leave this line as is) 




출처 - https://www.linux.co.kr/superuserboard/view.html?id=320&code=oracle&start=550&position=