Here is the package specification: /* Filename on companion disk: register.sql */* CREATE OR REPLACE PACKAGE register_app IS /* || Enhances DBMS_APPLICATION_INFO by capturing performan
Trang 116 Sort Progression 0 1 1
16 dbms_application_info 9 1000 1000
3 rows selected
Each session is allocated a maximum of four rows in the V$SESSION_LONGOPS virtual table for tracking long operations Rows are identified by the combination of context and stepid If calls to
DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS are made with more than four distinct
combinations of context and stepid, rows will be reưused in leastưrecentlyưused order.
All of the parameters except hint correspond directly to likeưnamed columns in the V$SESSION_LONGOPS virtual table While there are no restrictions on values stored in these columns, Oracle makes the following suggestions as a way of organizing information about the progress of long running operations:
stepsofar
If the longưrunning operation consists of distinct individual steps, the amount of work which has been done so far for this step.
steptotal
If the longưrunning operation consists of distinct individual steps, the total amount of work expected
to be done in this step.
sofar
The amount of work that has been done so far.
totalwork
The total amount of work expected to be done in this longưrunning operation.
application_data_1, application_data_2, application_data_3
Any numbers the client wishes to store.
Also note that all parameters to SET_SESSION_LONGOPS (except hint) default to zero This means that calls to the procedure need not specify values for all parameters, which is convenient in the case of such a long parameter list However, it also means that any unspecified parameters in a call to
SET_SESSION_LONGOPS will have their corresponding columns in V$SESSION_LONGOPS set to zero for that row after the call, which may not be the desired behavior.
7.1 Getting Started with
DBMS_APPLICATION_INFO
7.3 DBMS_APPLICATION_INFO
Examples
Copyright (c) 2000 O'Reilly & Associates All rights reserved
[Appendix A] What's on the Companion Disk?
Trang 27.3 DBMS_APPLICATION_INFO Examples
Oracle suggests that one way to extend DBMS_APPLICATION_INFO is to capture session performance statistics as part of the process of registering modules and actions To demonstrate how this might be done, I have created a package called register_app.
7.3.1 About the register_app Package
The programs in register_app are very similar to those in DBMS_APPLICATION_INFO Here is the package specification:
/* Filename on companion disk: register.sql */*
CREATE OR REPLACE PACKAGE register_app
IS
/*
|| Enhances DBMS_APPLICATION_INFO by capturing performance
|| statistics when module, action, or client_info are set
||
|| Statistics may be displayed in SQL*Plus for tracking and
|| debugging purposes A useful enhancement would be to
|| extend this idea to a logging feature, so stats are logged
|| to a table for analysis
||
|| Also enforces requirement that a module be registered before
|| an action can be registered
||
|| Author: John Beresniewicz, Savant Corp
|| Created: 09/01/97
||
|| Compilation Requirements:
||
|| SELECT on SYS.V_$MYSTAT
|| SELECT on SYS.V_$STATNAME
||
|| Execution Requirements:
||
||
*/
/* registers the application module */
PROCEDURE module
(module_name_IN IN VARCHAR2
,action_name_IN IN VARCHAR2 DEFAULT 'BEGIN');
/* registers the action within module */
PROCEDURE action(action_name_IN IN VARCHAR2);
/* registers additional application client information */
PROCEDURE client_info(client_info_IN IN VARCHAR2);
/* returns the currently registered module */
FUNCTION current_module RETURN VARCHAR2;
377
Trang 3/* returns the currently registered action */
FUNCTION current_action RETURN VARCHAR2;
/* returns the currently registered client info */
FUNCTION current_client_info RETURN VARCHAR2;
/* sets stat display for SQL*Plus ON (TRUE) or OFF (FALSE) */
PROCEDURE set_display_TF(display_ON_TF_IN IN BOOLEAN);
END register_app;
The module, action, and client_info programs of register_app correspond directly to the SET_MODULE, SET_ACTION, and SET_CLIENT_INFO programs of DBMS_APPLICATION_INFO; indeed, each of these programs eventually calls its counterpart The difference is that the programs in register_app first collect session performance information and store it in a private package global record, before calling the appropriate DBMS_APPLICATION_INFO program.
7.3.2 The action Procedure
Here is the body of the action procedure:
/* Filename on companion disk: register.sql */*
PROCEDURE action(action_name_IN IN VARCHAR2)
IS
BEGIN
/*
|| raise error if trying to register an action when module
|| has not been registered
*/
IF current_module IS NULL AND action_name_IN IS NOT NULL
THEN
RAISE_APPLICATION_ERROR(−20001, 'Module not registered');
ELSE
set_stats;
SYS.DBMS_APPLICATION_INFO.SET_ACTION(action_name_IN);
END IF;
END action;
Note that the action procedure is written to enforce the rule that an action can be registered only if a module has previously been registered The action procedure also calls a procedure called set_stats This procedure is private to the package, and does the work of collecting and saving resource statistics whenever new module, action, or client information is registered.
7.3.3 The set_stats Procedure
The set_stats procedure loads session performance information into a private global record named stat_rec Here are the definitions of stat_rec and the PL/SQL record type on which it is based:
/* record type to hold performance stats */
TYPE stat_rectype IS RECORD
(timer_hsecs NUMBER := 0
,logical_rds NUMBER := 0
,physical_rds NUMBER := 0
);
/* private global to hold stats at begin of each module/action */
stat_rec stat_rectype;
Now let's take a look at the set_stats procedure:
[Appendix A] What's on the Companion Disk?
Trang 4/* Filename on companion disk: register.sql/*
|| Gets current performance stats from V$MYSTAT and
|| sets the global record stat_rec If display_TF_ is TRUE
|| then uses DBMS_OUTPUT to display the stat differences
|| since last call to set_stats
*/
PROCEDURE set_stats
IS
temp_statrec stat_rectype;
diff_statrec stat_rectype;
/*
|| Embedded inline function to retrieve stats by name
|| from V$MYSTAT
*/
FUNCTION get_stat(statname_IN IN VARCHAR2)
RETURN NUMBER
IS
/* return value −9999 indicates problem */
temp_stat_value NUMBER := −9999;
/* cursor retrieves stat value by name */
CURSOR stat_val_cur(statname VARCHAR2)
IS
SELECT value
FROM sys.v_$mystat S
,sys.v_$statname N
WHERE
S.statistic# = N.statistic#
AND N.name = statname;
BEGIN
OPEN stat_val_cur(statname_IN);
FETCH stat_val_cur INTO temp_stat_value;
CLOSE stat_val_cur;
RETURN temp_stat_value;
EXCEPTION
WHEN OTHERS THEN
IF stat_val_cur%ISOPEN
THEN
CLOSE stat_val_cur;
END IF;
RETURN temp_stat_value;
END get_stat;
BEGIN
/*
|| load current values for performance statistics
*/
temp_statrec.timer_hsecs := DBMS_UTILITY.GET_TIME;
temp_statrec.logical_rds := get_stat('session logical reads');
temp_statrec.physical_rds := get_stat('physical reads');
/*
|| calculate diffs between current and previous stats
*/
diff_statrec.timer_hsecs :=
temp_statrec.timer_hsecs − stat_rec.timer_hsecs;
diff_statrec.logical_rds :=
temp_statrec.logical_rds − stat_rec.logical_rds;
diff_statrec.physical_rds :=
temp_statrec.physical_rds − stat_rec.physical_rds;
Trang 5/*
|| Both current module AND client info NULL indicates
|| initialization for session and stats should not be displayed
*/
IF display_TF AND
(current_module IS NOT NULL OR current_client_info IS NOT NULL)
THEN
DBMS_OUTPUT.PUT_LINE('Module: '||current_module);
DBMS_OUTPUT.PUT_LINE('Action: '||current_action);
DBMS_OUTPUT.PUT_LINE('Client Info: '||current_client_info);
DBMS_OUTPUT.PUT_LINE('Stats: '||
'elapsed secs:'||
TO_CHAR(ROUND(diff_statrec.timer_hsecs/100,2))||
', physical reads: '||TO_CHAR(diff_statrec.physical_rds)||
', logical reads: '||TO_CHAR(diff_statrec.logical_rds)
);
END IF;
/* OK, now initialize stat_rec to current values */
stat_rec := temp_statrec;
END set_stats;
The set_stats procedure logic is relatively straightforward:
1
Current values for the session performance statistics are gathered and the previous values (stored in the private global record stat_rec) are subtracted from them These differences represent the changes
in statistics since the last call to set_stats and are held in the record diff_statrec Note that this works even for the initial call to set_stats because the declaration of stat_rectype assigns a default value of zero to all fields Thus, on the first call, stat_rec will be initialized with zeros and diff_statrec will contain the current statistics.
2
The difference performance statistics are displayed using DBMS_OUTPUT if the display flag is set and this is not the first call to register application information.
3
Current values of the session performance statistics are saved in stat_rec for the next call to set_stats.
Exercise for the reader: Enhance the register_app package to log module and action performance statistics to
a table for resource accounting Be sure to allow for tracking by username and session.
7.3.4 The Information Procedures
The register_app package also contains three functions that return the currently registered information for the session These functions invoke the DBMS_APPLICATION_INFO procedures READ_MODULE and READ_CLIENT_INFO and return the respective information Procedures that return data in OUT parameters can often be encapsulated usefully with functions in this way This promotes more terse and readable code, as illustrated by the following code excerpts from the register_app package:
/* Filename on companion disk: register.sql */*
/* returns the currently registered module */
FUNCTION current_module RETURN VARCHAR2;
/* returns the currently registered client info */
FUNCTION current_client_info RETURN VARCHAR2;
PROCEDURE set_stats
[Appendix A] What's on the Companion Disk?