DBMS_APPLICATION_INFO是一个非常有用的程序包,他提供了通过V$SESSION
跟踪脚本运行情况的能力,该包允许你在v$session中的如下三列中填值:
CLIENT_INFO,MODULE,ACTION,该包不仅提供了设置这些列值的过程,还提供了
返回这些列值的过程,在CLIENT_INFO列中适合存放允许你的程序的客户端信息,
MODULE列适合存放你的主程序名,如包的名称,ACTION列适合存放你的程序包中
的过程名,现在我们先简单了解一下DBMS_APPLICATION_INFO的和V$session相关
的函数:


  dbms_application_info.set_client_info:允许你向v$session中写入你的客户端的信息
  dbms_application_info.set_module:允许你向v$session中写入你的主程序(如包)
  和你的过程的名称
  dbms_application_info.read_client_info:允许你从v$session中读取客户端的信息
  dbms_application_info.read_module:允许你从v$session中读取主程序(如包)
  和你的过程的名称

SYS@orclasm > desc dbms_application_info
PROCEDURE READ_CLIENT_INFO
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 CLIENT_INFO                    VARCHAR2                OUT
PROCEDURE READ_MODULE
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 MODULE_NAME                    VARCHAR2                OUT
 ACTION_NAME                    VARCHAR2                OUT
PROCEDURE SET_ACTION
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 ACTION_NAME                    VARCHAR2                IN
PROCEDURE SET_CLIENT_INFO
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 CLIENT_INFO                    VARCHAR2                IN
PROCEDURE SET_MODULE
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 MODULE_NAME                    VARCHAR2                IN
 ACTION_NAME                    VARCHAR2                IN
PROCEDURE SET_SESSION_LONGOPS
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 RINDEX                         BINARY_INTEGER          IN/OUT
 SLNO                           BINARY_INTEGER          IN/OUT
 OP_NAME                        VARCHAR2                IN     DEFAULT
 TARGET                         BINARY_INTEGER          IN     DEFAULT
 CONTEXT                        BINARY_INTEGER          IN     DEFAULT
 SOFAR                          NUMBER                  IN     DEFAULT
 TOTALWORK                      NUMBER                  IN     DEFAULT
 TARGET_DESC                    VARCHAR2                IN     DEFAULT
 UNITS                          VARCHAR2                IN     DEFAULT


SYS@orclasm > 


 
看一个简单的例子:




SQL> set serveroutput on
SQL> 
SQL> DECLARE
  2 l_clinent VARCHAR2(100);
  3 l_mod_name VARCHAR2(100);
  4 l_act_name VARCHAR2(100);
  5 BEGIN
  6 dbms_application_info.set_client_info('my client');
  7 dbms_application_info.read_client_info(l_clinent);
  8 dbms_output.put_line('client='||l_clinent);
  9 dbms_application_info.set_module('my mod','inserting');
 10 FOR i IN 1..100
 11 LOOP
 12 execute immediate 'INSERT INTO pp_test(c1) VALUES(:X)' USING i;
 13 END LOOP;
 14 dbms_application_info.read_module(l_mod_name,l_act_name);
 15 dbms_output.put_line('mod_name='||l_mod_name);
 16 dbms_output.put_line('act_name='||l_act_name);
 17 END;
 18  
 19 /
 
client=my client
mod_name=my mod
act_name=inserting
 
PL/SQL procedure successfully completed
 
SQL> commit;
 
Commit complete
 
SQL> select sid from v$mystat where rownum=1;
 
  SID
----------
  1065
 
SQL> SELECT sid,serial#,client_info,MODULE,action FROM v$session WHERE sid=1065;
 
  SID SERIAL# CLIENT_INFO MODULE ACTION
---------- ---------- ---------------------------------------------------------------- ------------------------------------------------ --------------------------------
  1065 18968 my client my mod inserting
 
再看一个更有用的例子:


 1.首先我们构建一个有大量数据的表:


SQL> DELETE FROM pp_test;
 
1320 rows deleted
 
SQL> insert into pp_test(c1) select object_name from all_objects;
 
116441 rows inserted
 
SQL> insert into pp_test(c1) select c1 from pp_test;
 
116441 rows inserted
 
SQL> insert into pp_test(c1) select c1 from pp_test;
 
232882 rows inserted
 
SQL> insert into pp_test(c1) select c1 from pp_test;
 
465764 rows inserted
 
SQL> commit;
 
Commit complete


 2.我们现在需要更新PP_TEST表的C1列,在脚本执行过程中我们需要知道
  已经处理的行数和已经花费的时间,执行结束后,我们需要知道处理的
  总的行数和执行的总时间,使用如下代码:
   
  --在session1中执行:
DECLARE
CURSOR cur_test IS
SELECT c1,ROWID
FROM pp_test;
l_new_c1 VARCHAR2(2000);
l_count_num PLS_INTEGER := 0;
l_start_time_num PLS_INTEGER;
BEGIN
l_start_time_num := DBMS_UTILITY.GET_TIME;
FOR cur_test_rec IN cur_test LOOP
l_count_num := l_count_num + 1;
l_new_c1 := cur_test_rec.c1||'_NEW';
UPDATE pp_test
SET c1 = l_new_c1
WHERE rowid = cur_test_rec.ROWID;
IF MOD(l_count_num, 1000) = 0 THEN
DBMS_APPLICATION_INFO.SET_MODULE('Records Processed: ' ||
l_count_num, 'Elapsed: ' || (DBMS_UTILITY.GET_TIME -
l_start_time_num)/100 || ' sec'); --每更新1000行,记录一次执行时间
END IF;
END LOOP;
COMMIT;
DBMS_APPLICATION_INFO.SET_MODULE('Records Processed: ' ||
l_count_num, 'Elapsed: ' || (DBMS_UTILITY.GET_TIME -
l_start_time_num)/100 || ' sec'); --更新结束,记录总的执行时间
END;


执行过程中我们可以查询v$session,如下所示:


SQL> SELECT sid,serial#,client_info,MODULE,action FROM v$session WHERE sid=307;
 
  SID SERIAL# CLIENT_INFO MODULE ACTION
---------- ---------- ---------------------------------------------------------------- ------------------------------------------------ --------------------------------
  307 36536 Records Processed: 360000 Elapsed: 18.69 sec
 
SQL> SELECT sid,serial#,client_info,MODULE,action FROM v$session WHERE sid=307;
 
  SID SERIAL# CLIENT_INFO MODULE ACTION
---------- ---------- ---------------------------------------------------------------- ------------------------------------------------ --------------------------------
  307 36536 Records Processed: 626000 Elapsed: 32.99 sec
 
SQL> SELECT sid,serial#,client_info,MODULE,action FROM v$session WHERE sid=307;
 
  SID SERIAL# CLIENT_INFO MODULE ACTION
---------- ---------- ---------------------------------------------------------------- ------------------------------------------------ --------------------------------
  307 36536 Records Processed: 837000 Elapsed: 44.56 sec
   
执行结束,我们再次查询v$session:


SQL> SELECT sid,serial#,client_info,MODULE,action FROM v$session WHERE sid=307;
 
  SID SERIAL# CLIENT_INFO MODULE ACTION
---------- ---------- ---------------------------------------------------------------- ------------------------------------------------ --------------------------------
  307 36536 Records Processed: 931528 Elapsed: 49.86 sec
 
SQL> 

 

 

Application developers can use the DBMS_APPLICATION_INFO package with Oracle Trace and the SQL trace facility to record names of executing modules or transactions in the database for later use when tracking the performance of various modules and debugging.

When an application registers with the database, its name and actions are recorded in the V$SESSION and V$SQLAREA views.

[   @more @]

Oracle DBMS_APPLICATION_INFO 用法例子

 

 

General Information Source {ORACLE_HOME}/rdbms/admin/dbmsapin.sql First Available 7.3.4 Constants Name Data Type Value set_session_longops_nohint BINARY_INTEGER -1 Dependencies DBMS_BACKUP_RESTORE EM_PING KUPV$FT DBMS_STATS EM_SEVERITY_REPOS KUPW$WORKER EMD_CRONOS_ADMIN gv_$session WWV_FLOW EMD_LOADER gv_$session_longop WWV_FLOW_SC_TRANSACTIONS EMD_MAINTENANCE gv_$sqlarea WWV_FLOW_SW_SCRIPT EMD_NOTIFICATION KUPM$MCP READ_CLIENT_INFO  Read the value of the client_info field of the current session dbms_application_info.set_client_info( client_info OUT VARCHAR2(64)); exec dbms_application_info.set_client_info('B%'); set serveroutput on DECLARE  x VARCHAR2(100);  BEGINdbms_application_info.read_client_info(x); dbms_output.put_line(x); END; / exec dbms_application_info.set_client_info('747'); DECLARE  x VARCHAR2(100);  BEGINdbms_application_info.read_client_info(x); dbms_output.put_line(x); END; /-- the following will not work but try it so that you understand why -- you can not use a stored procedure in a WHERE clauseCREATE OR REPLACE VIEW airplanes_view AS SELECT * FROM airplanes WHERE program_id = dbms_application_info.read_client_info(x);-- wrap the stored procedure so that it presents itself as a functionCREATE OR REPLACE FUNCTION app_info_wrapper RETURN VARCHAR2 IS x VARCHAR2(64);  BEGINdbms_application_info.read_client_info(x); RETURN x; END app_info_wrapper; /-- now you can create the view CREATE OR REPLACE VIEW airplanes_view AS SELECT * FROM airplanes WHERE program_id = app_info_wrapper; SELECT * FROM airplanes_view; exec dbms_application_info.set_client_info('777'); SELECT * FROM airplanes_view; READ_MODULE  Reads the values of the module and action fields of the current session dbms_application_info.read_module( module_name OUT VARCHAR2(48), action_name OUT VARCHAR2(32)); set serveroutput on DECLARE mod_in VARCHAR2(48); act_in VARCHAR2(32); mod_out VARCHAR2(48); act_out VARCHAR2(32); display_str VARCHAR2(200); BEGIN mod_in := 'Test Module'; act_in := 'Test Action';dbms_application_info.set_module(mod_in, act_in); dbms_lock.sleep(5);dbms_application_info.read_module(mod_out, act_out); display_str := 'Module Is '||mod_out||' and Action is '||act_out; dbms_output.put_line(display_str); END; / SET_ACTION Sets the name of the current action within the current module dbms_application_info.set_action(action_name IN VARCHAR2(32)); exec dbms_application_info.set_action('Load Departments'); SET_CLIENT_INFO  Set Client Info Field For The Session dbms_application_info.set_client_info(client_info IN VARCHAR2(64)); CREATE OR REPLACE VIEW btest AS SELECT object_name FROM all_objs WHERE object_name LIKE userenv('client_info'); SELECT * FROM btest; exec dbms_application_info.set_client_info('B%'); SELECT * FROM btest;--==================================== CREATE OR REPLACE VIEW vair AS SELECT * FROM airplanes WHERE program_id = userenv('client_info'); SELECT * FROM vair; exec dbms_application_info.set_client_info('747'); SELECT * FROM vair; SET_MODULE Sets the name of the module that is currently running dbms_application_info.set_module( module_name IN VARCHAR2(48), action_name IN VARCHAR2(32)); exec dbms_application_info.set_module('LOAD_TAB', 'Load Emp'); SET_SESSION_LONGOPS  Sets a row in the GV$SESSION_LONGOPS view dbms_application_info.set_session_longops( rindex IN OUT BINARY_INTEGER, slno IN OUT BINARY_INTEGER, op_name IN VARCHAR2(64) DEFAULT NULL, target IN BINARY_INTEGER DEFAULT 0, context IN BINARY_INTEGER DEFAULT 0, sofar IN NUMBER DEFAULT 0, totalwork IN NUMBER DEFAULT 0, target_desc IN VARCHAR2(32) DEFAULT 'unknown_target', units IN VARCHAR2(32) DEFAULT NULL); rindex constant to start a new row set_session_longops_nohint constant BINARY_INTEGER := -1; use returned value from previous call to reuse a row do not use slno ... for internal use by Oracle target is the object number being worked on sofar is any number indicating proress ... so far totalwork a best guess as to the 100% value ... on completion units used for sofar and totalwork CREATE TABLE test ( testcol NUMBER(10));-- Session 1 SELECT DISTINCT sid FROM gv$mystat;-- use this sid number in the session 2 query below DECLARE rindex BINARY_INTEGER; slno BINARY_INTEGER; sofar NUMBER(6,2);  target BINARY_INTEGER; totwork NUMBER := 100;  BEGIN rindex := dbms_application_info.set_session_longops_nohint; SELECT object_id INTO target FROM all_objs WHERE object_name = 'TEST'; FOR i IN 1 .. totwork LOOP sofar := i;dbms_application_info.set_session_longops(rindex, slno, 'PSOUG', target, 0, sofar, 100, 'Pct Complete'); INSERT INTO test VALUES (i); dbms_lock.sleep(0.25); END LOOP; COMMIT; END; /-- Session 2 substitute the sid returned above from session 1SELECT sid, serial#, schemaname FROM gv$session;  SELECT start_time, sofar, totalwork, time_remaining, elapsed_seconds FROM gv$session_longops WHERE sid = 140 AND serial# = 266; DBMS_APPLICATION_INFO Demo  Set Action Demo CREATE TABLE test ( testcol NUMBER(10));-- session 1 DECLARE mod_name VARCHAR2(48); act_name VARCHAR2(32);  BEGIN mod_name := 'read mod'; act_name := 'inserting';dbms_application_info.set_module(mod_name, act_name); FOR x IN 1..5 LOOP FOR i IN 1 ..60 LOOP INSERT INTO test VALUES (i); COMMIT; dbms_lock.sleep(1); END LOOP; act_name := 'deleting';dbms_application_info.set_action(act_name); FOR i IN 1 ..60 LOOP DELETE FROM test WHERE testcol = i; COMMIT; dbms_lock.sleep(1); END LOOP; END LOOP; END; /-- session 2 col module format a20 col action format a20 SELECT module, action FROM gv$session; SELECT module, action FROM gv$sqlarea; SELECT sql_text, disk_reads, module, action  FROM gv$sqlarea WHERE action = 'deleting';