This enhancement allows the procedure to close all database links for the session.. /* Filename on companion disk: mysess.sql */* /* || turns SQL tracing on/off with tag for file identif
Trang 1END close_links;
There are a few things to note in this procedure First, exceptions are declared and assigned to the two Oracle errors that can be raised by the DBMS_SESSION.CLOSE_DATABASE_LINK procedure This is done using PRAGMA EXCEPTION_INIT compiler directives Next comes a loop through all database links available to the user For each link in the loop, we execute DBMS_SESSION.CLOSE_DATABASE_LINK in a
BEGIN END block and trap the exceptions raised by links that were not open or in use Trapping the
exceptions allows the loop to continue until all links have been processed
Originally, the procedure would close only links that were not in use I decided to enhance it to accept a BOOLEAN parameter called force_with_commit_TF When this parameter is TRUE, the dblink_in_use exception handler issues a COMMIT This terminates the current transaction and frees all database links to be closed, including the one that raised the exception that is closed in the exception handler This enhancement allows the procedure to close all database links for the session
NOTE: The V$DBLINK virtual table shows database links that the current session has open.
The IN_TRANSACTION column indicates whether the open link is in use or can be closed
using DBMS_SESSION.CLOSE_DATABASE_LINK
11.1.5.6 The set_sql_trace procedure
The SQL trace facility is an invaluable tool for debugging application performance problems However, one problem that developers and DBAs often run into when using SQL trace is identifying the correct trace file from among the possibly hundreds of trace files that tend to collect and hang around in the directory specified
by the USER_DUMP_DEST parameter One technique is to put a literal tag in trace files by executing a SQL command such as the following:
SELECT 'JOHN B: TRACE 1' FROM DUAL;
When issued immediately after setting SQL_TRACE to TRUE, the statement will appear in the trace file, and
a utility like grep or awk can be used to scan the directory for the file with the correct literal tag In
my_session.set_sql_trace, I've enhanced DBMS_SESSION.SET_SQL_TRACE to accept a string tag and place it into the trace file when turning trace on The DBMS_SQL package is used to build and parse a SQL statement dynamically with the tag literal in it
/* Filename on companion disk: mysess.sql */*
/*
|| turns SQL tracing on/off with tag for file identification
*/
PROCEDURE set_sql_trace
(trace_TF IN BOOLEAN
,tag_IN IN VARCHAR2 DEFAULT USER)
IS
cursor_id INTEGER;
BEGIN
DBMS_SESSION.SET_SQL_TRACE(trace_TF);
IF trace_TF
THEN
cursor_id := DBMS_SQL.OPEN_CURSOR;
/* parse a SQL stmt with the tag in it */
DBMS_SQL.PARSE
(cursor_id
,'SELECT '''||tag_IN||''' FROM DUAL'
,DBMS_SQL.native);
DBMS_SQL.CLOSE_CURSOR(cursor_id);
END IF;
Trang 2END set_sql_trace;
Note that it is not necessary to execute the tag SQL statement; the parse will get it into the trace file After all, there is no need to do more work than absolutely required
11.1.5.7 The reset procedure
The DBMS_SESSION.RESET_PACKAGE procedure invalidates all package states, including all global variables and PL/SQL tables However, it does not free the memory associated with these now empty
structures; that is the job of DBMS_SESSION.FREE_UNUSED_USER_MEMORY The my_session.reset procedure combines these into a single call
/* Filename on companion disk: mysess.sql */*
/*
|| resets all package states and frees memory
*/
PROCEDURE reset
IS
BEGIN
DBMS_SESSION.RESET_PACKAGE;
DBMS_SESSION.FREE_UNUSED_USER_MEMORY;
END reset;
Originally, I designed the reset procedure to call load_unique_id and load_my_session_rec immediately after initializing the package and freeing memory The idea was that some package states should always be
available, so why not reinitialize them immediately? However, I had stepped into the
DBMS_SESSION.RESET_PACKAGE trap, which prevents any package state from being established within the same calling scope as the call to RESET_PACKAGE
It is good practice for programs that rely on package state to check expected package variables and initialize them if necessary
11.1.5.8 The memory procedure
The my_session.memory procedure was developed to provide experimental results from using
DBMS_SESSION.RESET and DBMS_SESSION.FREE_UNUSED_USER_MEMORY It uses
DBMS_OUTPUT to display the current session memory's UGA and PGA sizes If you ever wondered how much memory that big package really uses, check it out with my_session.memory
/* Filename on companion disk: mysess.sql */*
/*
|| displays session uga and pga using DBMS_OUTPUT
*/
PROCEDURE memory
IS
BEGIN
DBMS_OUTPUT.ENABLE;
DBMS_OUTPUT.PUT_LINE('session UGA: '||
TO_CHAR(my_session.statval('session uga memory') ) );
DBMS_OUTPUT.PUT_LINE('session PGA: '||
TO_CHAR(my_session.statval('session pga memory') ) );
END memory;
The memory procedure uses a function called statval, which returns the value of a V$SESSTAT statistic for the current session by name It's a handy little function
/* Filename on companion disk: mysess.sql */*
/*
|| returns current value of a statistic from
|| V$SESSTAT for this session
[Appendix A] What's on the Companion Disk?
Trang 3FUNCTION statval(statname_IN IN VARCHAR2) RETURN NUMBER
IS
CURSOR sesstat_cur (statname VARCHAR2)
IS
SELECT s.value
FROM sys.v_$sesstat s
,sys.v_$statname n
WHERE s.statistic# = n.statistic#
AND s.sid = my_session.sid
AND n.name = statname;
return_temp NUMBER;
BEGIN
OPEN sesstat_cur(statname_IN);
FETCH sesstat_cur INTO return_temp;
CLOSE sesstat_cur;
RETURN return_temp;
EXCEPTION
WHEN OTHERS THEN
IF sesstat_cur%ISOPEN
THEN
CLOSE sesstat_cur;
END IF;
RETURN NULL;
END statval;
Notice that statval uses the my_session.sid funtion in the cursor sesstat_cur
The following script demonstrates the inefficiency of PL/SQL tables of VARCHAR2 under Oracle 7.3 using
my_session.memory:
/* Filename on companion disk: sess2.sql */*
set serveroutput on size 100000
DECLARE
TYPE my_tabtype IS TABLE OF VARCHAR2(2000)
INDEX BY BINARY_INTEGER;
my_tab my_tabtype;
BEGIN
my_session.memory;
FOR i IN 1 1000
LOOP
my_tab(i) := TO_CHAR(i);
END LOOP;
my_session.memory;
END;
/
Here is sample output from executing this script:
session UGA: 36048 session PGA: 103328 session UGA: 36048 session PGA: 2248352
PL/SQL procedure successfully completed.
Even though each entry in the PL/SQL table my_tab has at most three characters, session PGA memory grew
by more than two megabytes! Luckily, this problem is fixed in PL/SQL8
III Server Management
Packages
11.2 DBMS_System:
Setting Events for
Trang 4Copyright (c) 2000 O'Reilly & Associates All rights reserved.
[Appendix A] What's on the Companion Disk?
Trang 511.2 DBMS_System: Setting Events for Debugging
The DBMS_SYSTEM package contains procedures for setting special internal trace events that can help the DBA or Oracle Technical Support personnel diagnose and debug serious database problems
The procedures in DBMS_SYSTEM are used by DBAs under special circumstances and should not be used
by end users or coded into applications Most of the procedures should be used only under specific
instructions from Oracle Technical Support, as improper usage can actually crash or damage the database The extremely useful SET_SQL_TRACE_IN_SESSION procedure, however, has less serious implications Both DBAs and developers should be aware of and know how to use it
11.2.1 Getting Started with DBMS_SYSTEM
The DBMS_SYSTEM package is created when the Oracle database is installed The dbmsutil.sql script (found
in the built−in packages source code directory, as described in Chapter 1) contains the source code for this
package's specification This script is called by catproc.sql, which is normally run immediately after database
creation
Unlike the other packages created by the dbmsutil.sql script, no public synonym for DBMS_SYSTEM is
created, and no privileges on the package are granted Thus, only the SYS user can normally reference and make use of this package Other users (or roles) can be granted access to DBMS_SYSTEM by having the SYS user issue the following SQL command:
GRANT EXECUTE ON DBMS_SYSTEM TO username;
In practice, it is probably better and safer to create a cover package around DBMS_SYSTEM and grant EXECUTE privilege on the cover package to specific users or roles, as indiscriminate use of the
DBMS_SYSTEM procedures can cause serious problems
NOTE: In Oracle 8.0, the DBMS_SYSTEM package specification was moved from the
dbmsutil.sql script into prvtutil.plb (the "wrapped" file), protecting it further from inadvertent
access
Table 11.2 lists the programs provided by this package
Table 11.2: DBMS_SYSTEM Programs
SQL?
READ_EV Reads trace event level for current session No
SET_EV Sets trace event levels in user session No