如今,一般DBA使用会话跟踪、SQL跟踪并进行分析已不是稀奇的事情,我估计常用的方法有SQL_TRACE、10046事件等。另外,如果我们需要跟踪其他会话,那需要如何做呢?大家估计最熟悉的是使用ORADEBUG。其实,Oracle提供的跟踪方法非常丰富,本文就将这些方法一一介绍,大家可以选择自己喜欢的方式并熟练使用它们。
TRACE目录
首先,我可能会关心咱跟踪的trace文件放在哪里,Oracle 10g和11g存放trace目录是不一样的,Oracle 10g中一般是$ORACLE_BASE/admin/$ORACLE_SID/udump和$ORACLE_BASE/admin/$ORACLE_SID/bdump(往往关心udump),而11g则引入ADR(Automatic Diagnostic Repository)新特性,trace文件就放于{adr_base}/diag/rdbms/{database_name}/$ORACLE_SID/trace下。
Oracle 11g Trace目录中{adr_base}如下查看:
1 SQL> show parameter diag 2 3 NAME TYPE VALUE 4 -------------------------- ----------- ------------------------------ 5 diagnostic_dest string /u01/app/oracle
跟踪文件的前台进程会被定向到USER_DUMP_DEST参数所指定的目录,而跟踪文件的后台进程则使用BACKGROUND_DUMP_DEST参数所指向的目录。无论在哪种情况下,TRACE的后缀都是.trc。
Oracle 10g中,我们可以如下查看trace目录:
1 SQL> show parameter user_dump_dest 2 3 NAME TYPE VALUE 4 ------------------------------------ ---------------------- ------------------------------ 5 user_dump_dest string /u01/app/oracle/admin/yft/udump 6 SQL> show parameter background_dump_dest 7 8 NAME TYPE VALUE 9 ------------------------------------ ---------------------- ------------------------------ 10 background_dump_dest string /u01/app/oracle/admin/yft/bdump 11 12
----或者通过查v$parameter获得---- 13 SQL> select name, value from v$parameter where name in ('user_dump_dest','background_dump_dest'); 14 15 NAME VALUE 16 ----------------------------------- ----------------------------------------------------------------- 17 background_dump_dest /u01/app/oracle/admin/yft/bdump 18 user_dump_dest /u01/app/oracle/admin/yft/udump
而Oracle 11g中,前台进程和后台进程所指定的trace目录是相同的
1 SQL> select name,value from v$parameter where name in ('user_dump_dest','background_dump_dest'); 2 3 NAME VALUE 4 ------------------------------ --------------------------------------------- 5 background_dump_dest /u01/app/oracle/diag/rdbms/yft/yft/trace 6 user_dump_dest /u01/app/oracle/diag/rdbms/yft/yft/trace
另外,如果查找当前会话的trace文件,也可以使用如下脚本:
1 SQL> column trace new_val T 2 SQL>select c.value || '/' || d.instance_name || '_ora_' || 3 a.spid || '.trc' || 4 case when e.value is not null then '_'||e.value end trace 5 from v$process a, v$session b, v$parameter c, v$instance d, v$parameter e 6 where a.addr = b.paddr 7 and b.audsid = userenv('sessionid') 8 and c.name = 'user_dump_dest' 9 and e.name = 'tracefile_identifier' 10 / 11 12 TRACE 13 -------------------------------------------------------------------------------- 14 /u01/app/oracle/diag/rdbms/yft/yft/trace/yft_ora_31139.trc
但如果你是普通用户,无法show parameter查看,那么可以通过如下方式获得trace目录:
1 SQL> set serveroutput on size 1000000 for wra 2 SQL> declare 3 2 paramname varchar2(256); 4 3 integerval binary_integer; 5 4 stringval varchar2(256); 6 5 paramtype binary_integer; 7 6 begin 8 7 paramtype:=dbms_utility.get_parameter_value('user_dump_dest',integerval,stringval); 9 8 if paramtype=1 then 10 9 dbms_output.put_line(stringval); 11 10 else 12 11 dbms_output.put_line(integerval); 13 12 end if; 14 13 end; 15 14 / 16 /u01/app/oracle/diag/rdbms/yft/yft/trace 17 18 PL/SQL procedure successfully completed.
这方法在11g中也适用,但11g的ADR特性让你更方便的获得trace目录,查询v$diag_info即可,如下:
1 SQL> select value from v$diag_info where name = 'Default Trace File'; 2 3 VALUE 4 ------------------------------------------------------------ 5 /u01/app/oracle/diag/rdbms/yft/yft/trace/yft_ora_31139.trc
Oracle为安全考虑,trace文件只能被oracle用户或者oinstall用户成员才能读取,其他用户试图读取该文件会收到错误报告,如下:
1 [oracle@yft ~]$ ll /u01/app/oracle/diag/rdbms/yft/yft/trace/ 2 total 440 3 -rw-r----- 1 oracle oinstall 34779 Feb 4 16:32 alert_yft.log 4 -rw-r----- 1 oracle oinstall 1065 Feb 4 16:18 yft_ckpt_30650.trc 5 -rw-r----- 1 oracle oinstall 59 Feb 4 16:18 yft_ckpt_30650.trm 6 -rw-r----- 1 oracle oinstall 920 Feb 4 16:22 yft_ckpt_30824.trc 7 。。。。。。 8 9 [jack@yft ~]$ id 10 uid=501(jack) gid=502(jack) groups=502(jack) 11 [jack@yft ~]$ cat /u01/app/oracle/diag/rdbms/yft/yft/trace/yft_ora_31139.trc 12 cat: /u01/app/oracle/diag/rdbms/yft/yft/trace/yft_ora_31139.trc: Permission denied
其实我们也可以让普通用户阅读trace内容,Oracle是通过一个隐含参数来控制这些限制的,即_trace_files_public,此隐含参数默认设置值为FALSE,即不允许普通用户阅读trace文件:
1 SQL> set pagesize 9999 2 SQL> set line 130 3 SQL> col NAME for a20 4 SQL> col VALUE for a20 5 SQL> col DESCRIB for a80 6 SQL> SELECT x.ksppinm NAME, y.ksppstvl VALUE, x.ksppdesc DESCRIB 7 2 FROM SYS.x$ksppi x, SYS.x$ksppcv y 8 3 WHERE x.inst_id = USERENV ('Instance') 9 4 AND y.inst_id = USERENV ('Instance') 10 5 AND x.indx = y.indx 11 6 AND x.ksppinm LIKE '%&par%' 12 7 / 13 Enter value for par: _trace_files_public 14 old 6: AND x.ksppinm LIKE '%&par%' 15 new 6: AND x.ksppinm LIKE '%_trace_files_public%' 16 17 NAME VALUE DESCRIB 18 -------------------- -------------------- -------------------------------------------------------------------------------- 19 _trace_files_public FALSE Create publicly accessible trace files
我们可以修改为TRUE来破坏这限制,如下:
1 SQL> alter system set "_trace_files_public"=TRUE scope=spfile; 2 3 System altered. 4 5 SQL> startup force 6 ORACLE instance started. 7 8 Total System Global Area 330600448 bytes 9 Fixed Size 1336344 bytes 10 Variable Size 226495464 bytes 11 Database Buffers 96468992 bytes 12 Redo Buffers 6299648 bytes 13 Database mounted. 14 Database opened. 15 SQL> oradebug setmypid 16 Statement processed. 17 SQL> oradebug tracefile_name 18 /u01/app/oracle/diag/rdbms/yft/yft/trace/yft_ora_31439.trc 19 SQL> ! ls -l /u01/app/oracle/diag/rdbms/yft/yft/trace/yft_ora_31439.trc 20 -rw-r--r-- 1 oracle oinstall 3120 Feb 4 17:30 /u01/app/oracle/diag/rdbms/yft/yft/trace/yft_ora_31439.trc
-可见普通用户已经有读取权限了(但,你真正去阅读的时候还会受目录的限制,也需要相应设置,不建议这么做)
跟踪级别(TRACE LEVEL)
玩转跟踪不了解跟踪级别是不行的,下面介绍下Oracle可采用的跟踪接口:
Level 0 = No statistics generated.
Level 1 = standard trace output including parsing,executes and fetches plus more.
Level 2 = Same as level 1.
Level 4 = Same as level 1 but includes bind information.
Level 8 = Same as level 1 but includes wait's information.
Level 12 = Same as level 1 but includes binds and waits
不光是10046事件,其它事件相关的level信息我们可阅读$ORACLE_HOME/rdbms/mesg/oraus.msg文件
跟踪当前会话
1、sql_trace
1 SQL> alter session set sql_trace=true; 2 3 SQL> ----execute our code 4 5 SQL> alter session set sql_trace=false;
2、10046 events
1 SQL> alter session set events '10046 trace name context forever,level 1'; 2 3 SQL> ----execute our code 4 5 SQL> alter session set events '10046 trace name context off';
另外,我们还可以使用dbms_system、dbms_support、dbms_monitor、oradebug方式进行跟踪,这些都在下面介绍。
跟踪其他会话
有的时候,我们需要用DBA权限用户去跟踪某个用户的SESSION,这时候,我们先要获取SID、SERIAL#或者进程号,方法如下:
1 SQL> select sid,serial# from v$session where sid = (select sid from v$mystat where rownum=1); 2 3 SID SERIAL# 4 ---------- ---------- 5 31 111 6 7 SQL> select sid from v$mystat where rownum=1; 8 9 SID 10 ---------- 11 31 12 13 SQL> select pid,spid from v$process p,v$session s where p.addr = s.paddr and s.sid = (select sid from v$mystat where rownum=1); 14 15 PID SPID 16 ---------- ------------------------ 17 19 5232 18 19 SQL> set linesize 150; 20 SQL> select s.sid,s.serial#,s.username,s.osuser 21 2 from v$session s,v$process p 22 3 where s.paddr = p.addr; 23 24 SID SERIAL# USERNAME OSUSER 25 ---------- ---------- ---------- ------------- 26 2 1 oracle 27 3 1 oracle 28 4 1 oracle 29 5 1 oracle 30 6 1 oracle 31 7 1 oracle 32 8 1 oracle 33 9 1 oracle 34 12 1 oracle 35 10 1 oracle 36 11 1 oracle 37 38 SID SERIAL# USERNAME OSUSER 39 ---------- ---------- ----------- --------------
40 13 1 oracle 41 14 1 oracle 42 15 1 oracle 43 16 1 oracle 44 31 111 JACK oracle 45 18 9 oracle 46 22 2 oracle 47 28 3 oracle 48 24 3 oracle 49 34 31 oracle 50 37 13 oracle 51 52 SID SERIAL# USERNAME OSUSER 53 ---------- ---------- ------------ -------------- 54 32 86 JACK oracle 55 56 23 rows selected.
下面介绍一下DBMS_SYSTEM和ORADEBUG的方法使用。
1、DBMS_SYSTEM
DBMS_SYSTEM是Oracle 10g之前常用的跟踪作用的包,虽然我们在Oracle 10g之后的版本无法看到这个包的相关说明,但功能还是能用的。
1 -设置时间相关统计收集 2 SQL> exec dbms_system.set_bool_param_in_session(31,111,'timed_statistics',true); 3 4 -设置max_dump_file_size以trace文件大小足够容纳信息 5 SQL> exec dbms_system.set_int_param_in_session(31,111,'max_dump_file_size',20000000); 6 7 -设置10046事件并且指定LEVEL,其中''说明跟踪的是当前session 8 SQL> exec dbms_system.set_ev(31,111,10046,12,''); 9 10 -激活trace跟踪 11 SQL> exec dbms_system.set_sql_trace_in_session(31,111,true); 12 13 -停止trace跟踪 14 SQL> exec dbms_system.set_sql_trace_in_session(31,111,false); 15 16 SQL> exec dbms_system.set_ev(31,111,10046,0,'');
下面进行一个演示:
1 SQL> conn /as sysdba 2 Connected. 3 SQL> select sid, serial# from v$session where sid = (select sid from v$mystat where rownum=1); 4 5 SID SERIAL# 6 ---------- ---------- 7 38 201 8 9 SQL> exec dbms_system.set_bool_param_in_session(38,201,'timed_statistics',true); 10 11 PL/SQL procedure successfully completed. 12 13 SQL> exec dbms_system.set_int_param_in_session(38,201,'max_dump_file_size',20000000); 14 15 PL/SQL procedure successfully completed. 16 17 SQL> exec dbms_system.set_ev(38,201,10046,12,''); 18 19 PL/SQL procedure successfully completed. 20 21 SQL> exec dbms_system.set_sql_trace_in_session(38,201,true); 22 23 PL/SQL procedure successfully completed. 24 25 SQL> variable x number; 26 SQL> exec :x:=1 27 28 PL/SQL procedure successfully completed. 29 30 SQL> select count(*) from jack.jack where object_id=:x; 31 32 COUNT(*) 33 ---------- 34 0 35 36 SQL> exec :x:=100 37 38 PL/SQL procedure successfully completed. 39 40 SQL> select count(*) from jack.jack where object_id=:x; 41 42 COUNT(*) 43 ---------- 44 1 45 46 SQL> exec dbms_system.set_sql_trace_in_session(38,201,false); 47 48 PL/SQL procedure successfully completed. 49 50 SQL> exec dbms_system.set_ev(38,201,10046,0,''); 51 52 PL/SQL procedure successfully completed. 53 54 SQL> select value from v$diag_info where name = 'Default Trace File'; 55 56 VALUE 57 -------------------------------------------------------------------------------- 58 /u01/app/oracle/diag/rdbms/yft/yft/trace/yft_ora_6212.trc ----trace文件内容:
59 60 ===================== 61 PARSING IN CURSOR #2 len=21 dep=0 uid=0 oct=47 lid=0 tim=1360036615100574 hv=3506322772 ad='2e7260c8' sqlid='bfjvfuv8gwgan' 62 BEGIN :x:=100; END; 63 END OF STMT 64 PARSE #2:c=1999,e=1898,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=0,tim=1360036615100569 65 EXEC #2:c=2000,e=2733,p=0,cr=0,cu=0,mis=1,r=1,dep=0,og=1,plh=0,tim=1360036615103614 66 67 *** 2013-02-05 11:56:57.464 68 CLOSE #2:c=0,e=49,dep=0,type=0,tim=1360036617464813 69 ===================== 70 PARSING IN CURSOR #1 len=49 dep=0 uid=0 oct=3 lid=0 tim=1360036617465230 hv=495547162 ad='2e494808' sqlid='gp8rd4wfskwsu' 71 select count(*) from jack.jack where object_id=:x 72 END OF STMT 73 PARSE #1:c=0,e=87,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=1205023501,tim=1360036617465225 74 EXEC #1:c=0,e=61,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=1205023501,tim=1360036617465434 75 FETCH #1:c=11999,e=12160,p=0,cr=1037,cu=0,mis=0,r=1,dep=0,og=1,plh=1205023501,tim=1360036617477676 76 STAT #1 id=1 cnt=1 pid=0 pos=1 obj=0 op='SORT AGGREGATE (cr=1037 pr=0 pw=0 time=0 us)' 77 STAT #1 id=2 cnt=1 pid=1 pos=1 obj=74560 op='TABLE ACCESS FULL JACK (cr=1037 pr=0 pw=0 time=0 us cost=289 size=156 card=12)' 78 FETCH #1:c=0,e=6,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,plh=1205023501,tim=1360036617478795 79 80 *** 2013-02-05 11:57:08.327 81 CLOSE #1:c=0,e=34,dep=0,type=0,tim=1360036628327862 82 =====================
2、ORADEBUG
ORADEBUG功能非常强大,我们执行oradebug help将会看到非常多的功能可使用。
ORADEBUG是SYS的工具,即使权限较大的SYSTEM用户都无法使用它:
1 SQL> show user; 2 USER is "SYSTEM" 3 SQL> oradebug setmypid 4 ORA-01031: insufficient privileges
因此,oradebug能跟踪SYS用户的当前SESSION,如下方式:
SQL> oradebug setmypid Statement processed. SQL> oradebug unlimit Statement processed. SQL> oradebug event 10046 trace name context forever,level 12 Statement processed. SQL> exec our code SQL> oradebug event 10046 trace name context off Statement processed. SQL> oradebug tracefile_name /u01/app/oracle/diag/rdbms/yft/yft/trace/yft_ora_5277.trc
当然,我们通过oradebug非常方便地跟踪其他会话,如下方式:
1 SQL> select pid, spid from v$process p, v$session s where p.addr = s.paddr and s.sid=(select sid from v$mystat where rownum=1); 2 3 PID SPID 4 ---------- -------------- 5 27 5323 6 ----指定跟踪SESSION的SPID(OS process)
7 SQL> oradebug setospid 5323 8 Oracle pid: 27, Unix process pid: 5323, image: oracle@yft (TNS V1-V3) ----或者指定跟踪SESSION的PID(Oracle process ID)
9 SQL> oradebug setorapid 27 10 Oracle pid: 27, Unix process pid: 5323, image: oracle@yft (TNS V1-V3) 11 SQL> oradebug unlimit 12 Statement processed. 13 SQL> oradebug event 10053 trace name context forever,level 1 14 Statement processed. 15 SQL> exec our code 16 SQL> oradebug event 10053 trace name context off 17 Statement processed. 18 SQL> oradebug tracefile_name 19 /u01/app/oracle/diag/rdbms/yft/yft/trace/yft_ora_5323.trc