Oracle Trace Event 10046 Notes

Introduction

This document covers Oracle 10046 event tracing functionality.  This is also termed SQL Trace, and, as the name implies it traces SQL that a user session executes, giving diagnostics information, which is useful for general troubleshooting and performance tuning.  The 10046 trace can be used to tell you exactly what Oracle is doing and how log each of the steps takes.  Topic discussed here are the different trace levels, init.ora parameters required and the different tools available for turning tracing on and off.

 

10046 tracing works with all Oracle Versions 8i,9i,10g.  10g also has new functionality (dbms_monitor), which should be used in preference especially when tracing applications using shared server/connection pooling.

 

Exceptions

This document does not discuss how to read/interpret a raw trace file, how to use relevant oracle tools like tkprof for making trace files more “readable”, or the 10g dbms_monitor functionality.

 

Trace levels

Trace levels can be used to define the type of information in the trace file.  There are a number of different trace levels, which generate different logging information.

Levels of trace

1 – standard SQL trace no, no wait events, or bind variables.

4 – Bind variables only

8 – Wait events only

12 – Bind Variables and Wait Events

 

Init.ora/spfile parameters

There are a few init.ora parameters that need to be set for the sessions you want to trace.  They are as follows:

timed_statistics=true

This is only really required for the waits or sql timing information.  Should be enabled by default on most system.  Recommended.

 

max_dump_file_size=unlimited

This allows the trace file to grow as required bty the trace.  If this is not set to unlimited, then you may find your trace file does not cover all activity, and you will see a message similar to “*** DUMP FILE IS LIMITED TO xxxxx BYTES ***” at the end of your trace file..  Recommended.

 

tracefile_identifier = ‘test_trace’

As string which is used to form part of the trace filename when the trace file is created.  This is useful when you are tracing a number of sessions and you want to make it easier to find the tracefile.

 

NOTE: to set these parameters the user needs “alter session” privilege.

 

Enabling Tracing

There are various methods of enabling tracing, from alter session to oradebug, but its worth noting that you can use different methods to switch it on/off.  For example you could user dbms_support to turn it on and oradebug to switch off.  Different tools suite different options.

 

To enable SQL trace for your current session

This is the easiest trace to setup, as it involves  issuing only one alter session commend either:

alter session set sql_trace=true; 

If you want higher than a level 1 trace then you must set the 10046 event to trace the session, for example:

alter session set events ‘10046 trace name context forever, level 12’;

 

Enabling trace for another session that is already connected.

Option 1 – Use SQLPlus oradebug

First you need to get the SID from v$session, connect as sysdba in SQLPlus and you can use oradebug.

oradebug setorapid 16

oradebug event 10046 trace name context forever, level 12;


and to turn it off use:

oradebug setorapid 16

oradebug event 10046 trace name context off;

Option 2 – Use dbms_support package

This may not be installed, but the source is usually in $ORACLE_HOME/rdbms/admin/dbmssupp.sql, which must be run as SYS or a SYSDBA.

 

execute dbms_support.start_trace_in_session(:sid,:serial,waits=>true,binds=>false);

 

Where SID and SERIAL are taken from v$session.

 

And to turn off

 

execute dbms_support.stop_trace_in_session(:sid, :serial);

 

Option 3 Use the trace.sql script

The source code for this script is provided later in this document.  It asks which username you want to trace and traces all sessions connected as that user.  It lists the users currently connected, and the init.ora parameters related to tracing, and prompts for username, and trace level.  Please remember to only supply valid trace levels, and to logon as SYSDBA.

To turn the tacing off, simply run the script again, and specify a level of zero.

 

An example of using the trace.sql script

 

SQL*Plus: Release 9.2.0.5.0 - Production on Mon Feb 7 15:29:51 2005

 

Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.

 

Enter password: ********

 

Connected to:

Oracle9i Enterprise Edition Release 9.2.0.3.0 - 64bit Production

With the Partitioning, OLAP and Oracle Data Mining options

JServer Release 9.2.0.3.0 - Production

 

SQL> @trace

 

USERNAME                       CONNECTIONS

------------------------------ -----------

CROMEYR                                  1

F5BACKUP                                 8

IANRILEY                                 1

JOHND                                    1

NETCOOL                                  2

PATROL2000                               1

RUSSELLS2                                4

SIMON                                    8

WEBUSER                                 16

 

NAME                           VALUE                ISMODI

------------------------------ -------------------- ------

timed_statistics               TRUE                 FALSE

max_dump_file_size             UNLIMITED            FALSE

Trace all sessions for one user.  Enter username to trace: netcool

Trace Level 0=none/off (default), 1=sql_trace 4=binds 8=waits 12=binds and waits : 12

 

oradebug setorapid 59

 oradebug event 10046 trace name context forever, level 12;

 

 

ORA-01031: insufficient privileges

ORA-01031: insufficient privileges

 

This is because you are trying to run oradebug to enable the trace, but you are not connected as SYSDBA.  Now try to connect as SYSDBA and re-run the trace.

 

SQL> connect johnd@TEST01 as sysdba

Enter password: ********

Connected.

SQL> @trace

 

USERNAME                       CONNECTIONS

------------------------------ -----------

CROMEYR                                  1

F5BACKUP                                 8

IANRILEY                                 1

NETCOOL                                  2

PATROL2000                               1

RUSSELLS2                                4

SIMON                                    8

WEBUSER                                 16

 

NAME                           VALUE                ISMODI

------------------------------ -------------------- ------

timed_statistics               TRUE                 FALSE

max_dump_file_size             UNLIMITED            FALSE

Trace all sessions for one user.  Enter username to trace: netcool

Trace Level 0=none/off (default), 1=sql_trace 4=binds 8=waits 12=binds and waits : 12

 

The output from the script is the oradebug commends which are executed:

 

oradebug setorapid 16

 oradebug event 10046 trace name context forever, level 12;

 

 

oradebug setorapid 71

 oradebug event 10046 trace name context forever, level 12;

 

 

Unix process pid: 23539, image: oracle@test-sun-01.localnet (TNS V1-V3)

Statement processed.

Unix process pid: 8040, image: oracle@test-sun-01.localnet (TNS V1-V3)

Statement processed.

 

When the user has finished the activity you want to trace, then you need to remember to turn it off.  Run the script again, select the same username, but enter zero (“0”) for the trace level.

 

SQL> @trace

 

USERNAME                       CONNECTIONS

------------------------------ -----------

CROMEYR                                  1

F5BACKUP                                 8

IANRILEY                                 1

NETCOOL                                  2

PATROL2000                               1

RUSSELLS2                                4

SIMON                                    8

WEBUSER                                 16

 

NAME                           VALUE                ISMODI

------------------------------ -------------------- ------

timed_statistics               TRUE                 FALSE

max_dump_file_size             UNLIMITED            FALSE

Trace all sessions for one user.  Enter username to trace: netcool

Trace Level 0=none/off (default), 1=sql_trace 4=binds 8=waits 12=binds and waits : 0

 

oradebug setorapid 16

 oradebug event 10046 trace name context off;

 

oradebug setorapid 71

 oradebug event 10046 trace name context off;

 

Unix process pid: 23539, image: oracle@test-sun-01.localnet (TNS V1-V3)

Statement processed.

Unix process pid: 8040, image: oracle@test-sun-01.localnet (TNS V1-V3)

Statement processed.

SQL>

 

Note here that the oradebug commands set the trace level to off.

 

How do I trace an OS process  that I don’t know the SID/SERIAL or username for?

If you know the UNIX process ID, for example, you got it from the “top” command, then you can use oradebug to turn on tracing for that process.  This is assuming it is a shadow server side process, rather than any general oracle process.  Please note that turning on tracing for some of the mandatory oracle background processes, like PMON, can sometimes cause the instance to crash!

 

test-sun-01.localnet[oracle]:TEST01:$ ps -ef

     UID   PID  PPID  C    STIME TTY      TIME CMD

...

  oracle 12449 12441  0 13:41:57 ?        0:00 oracleTEST01 (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))

....

SQL> oradebug setospid

ORA-00073: command SETOSPID takes between 1 and 1 argument(s)

SQL> oradebug setospid 12449

Statement processed.

SQL> oradebug event 10046 trace name context forever, level 12;

Statement processed.

 

 

Wait for the session to run a while....then turn off tracing and look for the trace file.

 
 

SQL>  oradebug event 10046 trace name context off;         

Statement processed.

 

Setting init.ora parameters for remote (other) sessions

dbms_system.set_bool_param_in_session (:sid,:serial,’timed_statistics’,true);

 

dbms_system.set_int_param_in_session (:sid,:serial,’max_dump_file_size’,2147483647);

 

Tracing, can also be turned on using dbms_system.set_ev procedure.  This can in fact be used to set any event.  Be careful when using this as if you get the incorrect event number all kinds of weird things can happen including instance crashes!

Here is an example of setting the 10046 trace event using set_ev procedure.

 

sys.dbms_system.set_ev(:sid,:serial,10046,8,’’)

 

And to turn off

sys.dbms_system.set_ev(:sid,:serial,10046,0,’’)

 

 

How can I tell if my session has tracing turned on?

The dbms_system.read_ev procedure can be used for this.  As can be seen below:

declare

event_level number;

begin

dbms_system.read_ev(10046,event_level);

dbms_output.put_line('Event 10046 set at level '|| to_char(event_level));

end;

/

Where can I find my trace files?

Trace files will usually be in the user_dump_destination (udump), but in shared server configurations you will also find trace file in background_dump_destination (bdump).

 

How can I tell if a session already has tracing enabled? i.e. it was enabled by a trigger.

I am unaware of any method to find if an event is set for a remote session.  For the current session use the dbms_system.read_ev as described above.

 

Known issues/problems

Oracle Multi-Threaded Server (MTS) connections to the database are difficult to trace, as the trace information for the session I n question is likely to be a number of trace files.  You need to match the session ID that begins with the line *** in all the trace files, then put then in date/time order.  This effectively leaves you with a virtual trace file.  Its quite tricky, especially if you have a large number of shared server processes.  Where possible try and configure the client to use a dedicated server connection, so that you have one trace file

Connection pooling applications are difficult to trace as you need to trace the whole pool to make sure that you get all the information required from the trace.

 

NOTE : Oracle 10g trace functionality has been improved considerably in this area.  In 10g the dbms_monitor package can be used to trace sessions, and you can check which sessions have tracing enabled by looking at dba_enabled_traces

 

Enabling Tracing with a logon trigger

If you find it difficult to trace a session because it logs in and does stuff before you have time to trace, try implementing a database logon trigger such as the one below:

 

CREATE OR REPLACE TRIGGER enable_10046_trace_trigger

after logon on database

--    10046 TRACELEVELS

--    0  - Turn off tracing.

--    1  - Basic SQL_TRACE.

--    4  - Level 1 plus Bind Variables.

--    8  - Level 1 plus wait events.

--    12 - Level 1 plus Bind Variables and Wait event information.

begin

if user ='JOHND' then

  execute immediate 'alter session set timed_statistics = true';

  execute immediate 'alter session set max_dump_file_size = unlimited';

  execute immediate 'alter session set tracefile_identifier = ''session_trace_energis''';

  execute immediate 'alter session set events ''10046 trace name context forever, level 4'' '; -- bind variables only

end if;

end;

Or if you need to be a little more specific about the users/sessions you want to trace, then you could use something like the following:

CREATE OR REPLACE TRIGGER SYS.enable_10046_trace_trigger
   AFTER LOGON ON DATABASE
--  10046 TRACELEVELS
-- 0  - Turn off tracing.
-- 1  - Basic SQL_TRACE.
-- 4  - Level 1 plus Bind Variables.
-- 8  - Level 1 plus wait events.
-- 12 - Level 1 plus Bind Variables and Wait event information.
DECLARE
   v_exe       v$session.program%TYPE;   -- EXE (Program used to connect) - See v$session
   v_sid       v$session.SID%TYPE;       -- SID for this session
   v_osuser    v$session.osuser%TYPE;
   v_machine   v$session.machine%TYPE;
   v_ok        VARCHAR (10);
-- Flag for everything OK - Can't be boolean coz decode doesn't like booleans
BEGIN
--To check the program need to get the sid for this session.
-- SID
   SELECT SID
     INTO v_sid
     FROM v$mystat
    WHERE ROWNUM < 2;

-- Program executable for this session
   SELECT program
     INTO v_exe
     FROM v$session
    WHERE SID = v_sid;

-- OSUSER Details
   SELECT osuser
     INTO v_osuser
     FROM v$session
    WHERE SID = v_sid;

--Machine Details
   SELECT machine
     INTO v_machine
     FROM v$session
    WHERE SID = v_sid;

   IF USER = 'PHONE_USER' AND v_exe = 'phone.exe' AND v_osuser = 'smithj' and v_machine='WG1\WS00001'
   THEN
      EXECUTE IMMEDIATE 'alter session set timed_statistics = true';
      EXECUTE IMMEDIATE 'alter session set max_dump_file_size = unlimited';
      EXECUTE IMMEDIATE 'alter session set tracefile_identifier = ''session_trace_trigger''';
      EXECUTE IMMEDIATE 'alter session set events ''10046 trace name context forever, level 4'' ';
      DBMS_SESSION.set_identifier ('SQL TRACE ENABLED VIA LOGIN TRIGGER');
   END IF;
END;

Script to determine which events are set in the current session

 

Run this script in SQLPlus as SYSDBA

  

rem what_events.sql

rem List the events that are set this this current session.

rem

declare

event_level number;

counter number;

begin

counter:=0;

for i in 10000..10999 loop

  dbms_system.read_ev(i,event_level);

  if (event_level > 0) then

    dbms_output.put_line('Event '||to_char(i)||' set at level '|| to_char(event_level));

    counter:=counter+1;

  end if;

end loop;

if (counter= 0 ) then

  dbms_output.put_line('No events set for this session');

end if;

end;

/

 

trace.sql – trace all sessions for a given username

 

rem **********************************

rem   Name : trace.sql

rem   Description:

rem     Turn on/off 10046 SQL trace event

rem   for all sessions connected as a particular database user.

rem   Uses the "ORADEBUG" method to set the event, so this script MUST be run via SQL*Plus.

rem   Remember you need timed_statistics=true to get timing info in the trace file.

rem     and max_dump_file_size settijng to a high enough value to stop

rem   the trace file getting truncated.

rem   Run the script again with a level of 0 to turn off tracing.

rem   10046 TRACELEVELS

rem   0  - Turn off tracing.

rem   1  - Basic SQL_TRACE.

rem   4  - Level 1 plus Bind Variables.

rem   8  - Level 1 plus wait events.

rem   12 - Level 1 plus Bind Variables and Wait event information.

rem

rem History:

rem Date    Who   Desc

rem 28/09/2004    JAD   Created

rem

rem **********************************

 

set feedback off

column name format a30

column value format a20

column ismodified format a6

 

select username, count(1) connections from v$session

where username <>'SYS' and username is not null group by username;

 

select name,value,ismodified from v$parameter

where name ='timed_statistics' or name='max_dump_file_size';

 

accept traceuser char default SCOTT PROMPT 'Trace all sessions for one user.  Enter username to trace: '

accept tracelevel NUMBER DEFAULT 0 PROMPT 'Trace Level 0=none/off (default), 1=sql_trace 4=binds 8=waits 12=binds and waits : '

 

set heading off

set serverout off

set verify off

 

 

spool tracetmp.sql

 

SELECT  'oradebug setorapid '||pid ||chr(10)||chr(13)||

            'oradebug event 10046 trace name context '||

              decode (&&tracelevel,0,'off','forever, level '||&&tracelevel)||';'||chr(10)||chr(13)

FROM v$process a, v$session b

WHERE a.addr=b.paddr

AND b.username=upper('&&traceuser');

 

spool off;

 

@tracetmp.sql

 

set heading on

set serverout on

set verify on

set feedback on

rem host notepad tracetmp.sql