END 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; [Appendix A] What's on the Companion Disk? 11.1.5 DBMS_SESSION Examples 536 END 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? 11.1.5 DBMS_SESSION Examples 537 */ FUNCTION 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 [Appendix A] What's on the Companion Disk? 11.1.5 DBMS_SESSION Examples 538 Debugging Copyright (c) 2000 O'Reilly & Associates. All rights reserved. [Appendix A] What's on the Companion Disk? 11.1.5 DBMS_SESSION Examples 539 Chapter 11 Managing Session Information 11.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 Name Description Use in SQL? READ_EV Reads trace event level for current session No SET_EV Sets trace event levels in user session No 540 . 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. 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. 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