DBMS_APPLICATION_INFO包的使用


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 用法例子

from:http://www.psoug.org/reference/dbms_applic_info.html


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); 
BEGIN
dbms_application_info.read_client_info(x);
dbms_output.put_line(x);
END;
/

exec dbms_application_info.set_client_info('747');

DECLARE 
x VARCHAR2(100); 
BEGIN
dbms_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 clause
CREATE 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); 
BEGIN
dbms_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';














About Me

...............................................................................................................................

本文整理自网络:http://blog.csdn.net/zhpsam109/article/details/3716373、http://blog.itpub.net/271283/viewspace-997571/

本文在itpubhttp://blog.itpub.net/26736162)、博客园http://www.cnblogs.com/lhrbest和个人微信公众号(xiaomaimiaolhr)上有同步更新

本文pdf小麦苗云盘地址:http://blog.itpub.net/26736162/viewspace-1624453/

● QQ群:230161599     微信群:私聊

联系我请加QQ好友(642808185),注明添加缘由

文章内容来源于小麦苗的学习笔记,部分整理自网络,若有侵权或不当之处还请谅解

版权所有,欢迎分享本文,转载请保留出处

...............................................................................................................................

拿起手机使用微信客户端扫描下边的左边图片来关注小麦苗的微信公众号:xiaomaimiaolhr,扫描右边的二维码加入小麦苗的QQ群,学习最实用的数据库技术。

DBMS_APPLICATION_INFO包的使用DBMS_APPLICATION_INFO包的使用

 DBMS_APPLICATION_INFO包的使用  DBMS_APPLICATION_INFO包的使用

上一篇:thickbox 关于动态生成 无法跳出弹出框的问题


下一篇:juquery源码研究:addEventListener与attachEvent区别