如今,一般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}如下查看:
luocs@MAA> show parameter diag
NAME TYPE VALUE
------------------------------------ ---------------------- ------------------------------
diagnostic_dest string /u01/app/oracle
跟踪文件的前台进程会被定向到USER_DUMP_DEST参数所指定的目录,而跟踪文件的后台进程则使用BACKGROUND_DUMP_DEST参数所指向的目录。无论在哪种情况下,TRACE的后缀都是.trc。
Oracle 10g中,我们可以如下查看trace目录
sys@LTB> show parameter user_dump_dest
NAME TYPE VALUE
------------------------------------ ---------------------- ------------------------------
user_dump_dest string /u01/app/oracle/admin/ltb/udump
sys@LTB> show parameter background_dump_dest
NAME TYPE VALUE
------------------------------------ ---------------------- ------------------------------
background_dump_dest string /u01/app/oracle/admin/ltb/bdump
或者通过查v$parameter获得
sys@LTB> select name, value from v$parameter where name in ('user_dump_dest','background_dump_dest');
NAME VALUE
----------------------------------- -----------------------------------------------------------------
background_dump_dest /u01/app/oracle/admin/ltb/bdump
user_dump_dest /u01/app/oracle/admin/ltb/udump
而Oracle 11g中,前台进程和后台进程所指定的trace目录是相同的
sys@MAA> select name, value from v$parameter where name in ('user_dump_dest','background_dump_dest');
NAME VALUE
-------------------- -----------------------------------------------------------------
background_dump_dest /u01/app/oracle/diag/rdbms/maa/maa/trace
user_dump_dest /u01/app/oracle/diag/rdbms/maa/maa/trace
另外,如果查找当前会话的trace文件,也可以使用如下脚本:
sys@LTB> column trace new_val T
sys@LTB> select c.value || '/' || d.instance_name || '_ora_' ||
2 a.spid || '.trc' ||
3 case when e.value is not null then '_'||e.value end trace
4 from v$process a, v$session b, v$parameter c, v$instance d, v$parameter e
5 where a.addr = b.paddr
6 and b.audsid = userenv('sessionid')
7 and c.name = 'user_dump_dest'
8 and e.name = 'tracefile_identifier'
9 /
TRACE
------------------------------------------------------------------
/u01/app/oracle/admin/ltb/udump/ltb_ora_3471.trc
但如果你是普通用户,无法show parameter查看,那么可以通过如下方式获得trace目录:
luocs@LTB> set serveroutput on size 1000000 for wra
luocs@LTB> declare
2 paramname varchar2(256);
3 integerval binary_integer;
4 stringval varchar2(256);
5 paramtype binary_integer;
6 begin
7 paramtype:=dbms_utility.get_parameter_value('user_dump_dest',integerval,stringval);
8 if paramtype=1 then
9 dbms_output.put_line(stringval);
10 else
11 dbms_output.put_line(integerval);
12 end if;
13 end;
14 /
/u01/app/oracle/admin/ltb/udump
PL/SQL procedure successfully completed.
这方法在11g中也适用,但11g的ADR特性让你更方便的获得trace目录,查询v$diag_info即可,如下:
luocs@MAA> select value from v$diag_info where name = 'Default Trace File';
VALUE
----------------------------------------------------------------------------------------------------
/u01/app/oracle/diag/rdbms/maa/maa/trace/maa_ora_15852.trc
Oracle为安全考虑,trace文件只能被oracle用户或者oinstall用户组成员才能读取,其他用户试图读取该文件会收到错误报告,如下:
[root@primary ~]# ls -l /u01/app/oracle/admin/ltb/udump/
total 40
-rw-r----- 1 oracle oinstall 638 Jan 21 20:12 ltb_ora_27185.trc
-rw-r----- 1 oracle oinstall 954 Jan 21 20:13 ltb_ora_27217.trc
[luocs@primary ~]$ id
uid=501(luocs) gid=502(luocs) groups=502(luocs)
[luocs@primary ~]$ cat /u01/app/oracle/admin/ltb/udump/ltb_ora_27185.trc
cat: /u01/app/oracle/admin/ltb/udump/ltb_ora_27185.trc: Permission denied
其实我们也可以让普通用户阅读trace内容,Oracle是通过一个隐含参数来控制这些限制的,即_trace_files_public,此隐含参数默认值为FALSE,即不允许普通用户阅读trace文件:
sys@MAA> set pagesize 9999
sys@MAA> set line 130
sys@MAA> col NAME for a20
sys@MAA> col VALUE for a20
sys@MAA> col DESCRIB for a80
sys@MAA> SELECT x.ksppinm NAME, y.ksppstvl VALUE, x.ksppdesc DESCRIB
2 FROM SYS.x$ksppi x, SYS.x$ksppcv y
3 WHERE x.inst_id = USERENV ('Instance')
4 AND y.inst_id = USERENV ('Instance')
5 AND x.indx = y.indx
6 AND x.ksppinm LIKE '%&par%'
7 /
Enter value for par: _trace_files_public
old 6: AND x.ksppinm LIKE '%&par%'
new 6: AND x.ksppinm LIKE '%_trace_files_public%'
NAME VALUE DESCRIB
-------------------- -------------------- --------------------------------------------------------------------------------
_trace_files_public FALSE Create publicly accessible trace files
我们可以修改为TRUE来破坏这限制,如下:
sys@LTB> alter system set "_trace_files_public"=TRUE scope=spfile;
System altered.
sys@LTB> startup force
ORACLE instance started.
Total System Global Area 520093696 bytes
Fixed Size 2021984 bytes
Variable Size 150996384 bytes
Database Buffers 360710144 bytes
Redo Buffers 6365184 bytes
Database mounted.
Database opened.
sys@LTB> oradebug setmypid
Statement processed.
sys@LTB> oradebug tracefile_name
/u01/app/oracle/admin/ltb/udump/ltb_ora_3608.trc
sys@LTB> ! ls -l /u01/app/oracle/admin/ltb/udump/ltb_ora_3608.trc
-rw-r--r-- 1 oracle oinstall 1752 Jan 21 20:39 /u01/app/oracle/admin/ltb/udump/ltb_ora_3608.trc
�C 可见普通用户已经有读取权限了(但,你真正去阅读的时候还会受目录的限制,也需要相应设置,不建议这么做)
跟踪级别(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
luocs@MAA> alter session set sql_trace=true;
luocs@MAA> ― execute our code
luocs@MAA> alter session set sql_trace=false;
2、10046 events
luocs@MAA> alter session set events '10046 trace name context forever,level 1';
luocs@MAA> ― execute our code
luocs@MAA> alter session set events '10046 trace name context off';
另外,我们还可以使用dbms_system、dbms_support、dbms_monitor、oradebug方式进行跟踪,这些都在下面介绍。
跟踪其他会话
有的时候,我们需要用DBA权限用户去跟踪某个用户的SESSION,这时候,我们先要获取SID、SERIAL#或者进程号,方法如下:
-- 获取当前会话的SID,SERIAL#
luocs@MAA> select sid, serial# from v$session where sid = (select sid from v$mystat where rownum=1);
SID SERIAL#
---------- ----------
41 1147
-- 获取当前会话的PID和SPID
luocs@MAA> 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);
PID SPID
---------- ------------------------------------------------
24 16434
-- 获取系统级别的SID与SERIAL#等
sys@MAA> select s.sid,s.serial#,s.username,s.osuser
2 from v$session s,v$process p
3 where s.paddr=p.addr;
SID SERIAL# USERNAME OSUSER
---------- ---------- ---------- ----------
2 1 oracle
3 1 oracle
4 1 oracle
5 1 oracle
6 1 oracle
7 1 oracle
8 1 oracle
9 1 oracle
10 1 oracle
11 1 oracle
12 1 oracle
13 1 oracle
14 1 oracle
15 1 oracle
16 1 oracle
17 1 oracle
18 1 oracle
20 1 oracle
23 23 oracle
28 271 oracle
41 1149 LUOCS oracle
53 21805 LUOCS oracle
25 7 oracle
27 1 oracle
40 1127 SYS oracle
29 5 oracle
30 1 oracle
34 1 oracle
22 11 oracle
44 21617 SYS oracle
47 833 XLZHGJ oracle
38 3 oracle
37 13 oracle
21 79 oracle
48 1303 oracle
35 rows selected.
下面介绍几个跟踪会话方法
1、DBMS_SYSTEM
DBMS_SYSTEM是Oracle 10g之前常用的跟踪作用的包,虽然我们在Oracle 10g之后的版本无法看到这个包的相关说明,但功能还是能用的。
�C 设置时间相关统计收集
luocs@MAA> exec dbms_system.set_bool_param_in_session(41,1149,'timed_statistics',true);
�C 设置max_dump_file_size以trace文件大小足够容纳信息
luocs@MAA> exec dbms_system.set_int_param_in_session(41,1149,'max_dump_file_size',20000000);
�C 设置10046事件并且指定LEVEL
luocs@MAA> exec dbms_system.set_ev(41,1149,10046,12,'');
�C 激活trace跟踪
luocs@MAA> exec dbms_system.set_sql_trace_in_session(41,1149,true);
�C 停止trace跟踪
luocs@MAA> exec dbms_system.set_sql_trace_in_session(41,1149,false);
luocs@MAA> exec dbms_system.set_ev(41,1149,10046,0,'');
下面是我的演示内容:
luocs@MAA> select sid, serial# from v$session where sid = (select sid from v$mystat where rownum=1);
SID SERIAL#
---------- ----------
53 21805
luocs@MAA> exec dbms_system.set_bool_param_in_session(53,21805,'timed_statistics',true);
PL/SQL procedure successfully completed.
luocs@MAA> exec dbms_system.set_int_param_in_session(53,21805,'max_dump_file_size',20000000);
PL/SQL procedure successfully completed.
luocs@MAA> exec dbms_system.set_ev(53,21805,10046,12,'');
PL/SQL procedure successfully completed.
luocs@MAA> exec dbms_system.set_sql_trace_in_session(53,21805,true);
PL/SQL procedure successfully completed.
luocs@MAA> variable x number
luocs@MAA> exec :l := 1
PL/SQL procedure successfully completed.
luocs@MAA> select count(*) from test where id=:l;
COUNT(*)
----------
1
luocs@MAA> exec :l := 100
PL/SQL procedure successfully completed.
luocs@MAA> select count(*) from test where id=:l;
COUNT(*)
----------
9999
luocs@MAA> exec dbms_system.set_sql_trace_in_session(53,21805,false);
PL/SQL procedure successfully completed.
luocs@MAA> exec dbms_system.set_ev(53,21805,10046,0,'');
PL/SQL procedure successfully completed.
luocs@MAA> select value from v$diag_info where name = 'Default Trace File';
VALUE
----------------------------------------------------------------------------------------------------
/u01/app/oracle/diag/rdbms/maa/maa/trace/maa_ora_15826.trc
trace部分内容:
=====================
PARSING IN CURSOR #47603153651720 len=21 dep=0 uid=51 oct=47 lid=51 tim=1359462720172941 hv=3459344829 ad='9ed28e20' sqlid='0haapcz732udx'
BEGIN :l := 1; END;
END OF STMT
PARSE #47603153651720:c=0,e=670,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=0,tim=1359462720172939
EXEC #47603153651720:c=2000,e=1491,p=0,cr=0,cu=0,mis=1,r=1,dep=0,og=1,plh=0,tim=1359462720174513
PARSE #47603153650544:c=0,e=26,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=0,tim=1359462720174801
EXEC #47603153650544:c=0,e=186,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,plh=0,tim=1359462720175049
*** 2013-01-29 20:32:11.351
CLOSE #47603153651720:c=0,e=31,dep=0,type=0,tim=1359462731351173
CLOSE #47603153650544:c=0,e=38,dep=0,type=3,tim=1359462731351294
=====================
PARSING IN CURSOR #47603153651720 len=37 dep=0 uid=51 oct=3 lid=51 tim=1359462731351922 hv=874746037 ad='9ed283d0' sqlid='9pukpvhu2745p'
select count(*) from test where id=:l
END OF STMT
PARSE #47603153651720:c=0,e=546,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=0,tim=1359462731351921
EXEC #47603153651720:c=2000,e=2221,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=4002023942,tim=1359462731354222
FETCH #47603153651720:c=0,e=170,p=0,cr=2,cu=0,mis=0,r=1,dep=0,og=1,plh=4002023942,tim=1359462731354557
STAT #47603153651720 id=1 cnt=1 pid=0 pos=1 obj=0 op='SORT AGGREGATE (cr=2 pr=0 pw=0 time=174 us)'
STAT #47603153651720 id=2 cnt=1 pid=1 pos=1 obj=25916 op='INDEX RANGE SCAN INX_TEST_ID (cr=2 pr=0 pw=0 time=146 us cost=1 size=3 card=1)'
FETCH #47603153651720:c=0,e=1,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,plh=4002023942,tim=1359462731354893
PARSE #47603153650544:c=0,e=28,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=0,tim=1359462731355442
EXEC #47603153650544:c=0,e=206,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,plh=0,tim=1359462731355711
*** 2013-01-29 20:32:17.365
CLOSE #47603153651720:c=0,e=13,dep=0,type=0,tim=1359462737365691
CLOSE #47603153650544:c=0,e=25,dep=0,type=3,tim=1359462737365809
2、DBMS_SUPPORT
早期版本提供的跟踪相关包还有DBMS_SUPPORT,它可以跟踪用户的SESSION信息。DBMS_SUPPORT默认没有安装,我们需要手动执行脚本来安装
luocs@MAA> desc dbms_support
ERROR:
ORA-04043: object dbms_support does not exist
�C INSTALL THE PACKAGE
sys@MAA> @?/rdbms/admin/dbmssupp
Package created.
Package body created.
sys@MAA> @?/rdbms/admin/prvtsupp.plb
Package body created.
�C 查看版本
sys@MAA> select dbms_support.PACKAGE_VERSION from dual;
PACKAGE_VERSION
―――――――――――――――――――――――――――――――――――――――――――-
DBMS_SUPPORT Version 1.0 (17-Aug-1998) �C Requires Oracle 7.2 �C 8.0.5
�C 开启某session的跟踪,可以选择等待信息和绑定变量信息
sys@MAA> exec dbms_support.start_trace_in_session(53,21805,waits=>false,binds=>true);
�C 停止某session的跟踪
sys@MAA> exec dbms_support.stop_trace_in_session(53,21805)
�C 启动跟踪当前session
sys@MAA> exec dbms_support.start_trace(waits=>false,binds=>true);
�C 停止跟踪当前session
sys@MAA> exec dbms_support.stop_trace;
下面是我的演示:
luocs@MAA> select sid, serial# from v$session where sid = (select sid from v$mystat where rownum=1);
SID SERIAL#
---------- ----------
53 21807
sys@MAA> exec dbms_support.start_trace_in_session(53,21807,waits=>false,binds=>true);
PL/SQL procedure successfully completed.
luocs@MAA> variable x number
luocs@MAA> exec :l := 100
PL/SQL procedure successfully completed.
luocs@MAA> select count(*) from test where id=:l
2 ;
COUNT(*)
----------
9999
sys@MAA> exec dbms_support.stop_trace_in_session(53,21807);
PL/SQL procedure successfully completed.
luocs@MAA> select value from v$diag_info where name = 'Default Trace File';
VALUE
----------------------------------------------------------------------------------------------------
/u01/app/oracle/diag/rdbms/maa/maa/trace/maa_ora_16974.trc
-- 部分TRACE内容
=====================
PARSING IN CURSOR #47953679205472 len=38 dep=0 uid=51 oct=3 lid=51 tim=1359464472023679 hv=3115683868 ad='9e731000' sqlid='fsa2yt2wvb40w'
select count(*) from test where id=:l
END OF STMT
PARSE #47953679205472:c=999,e=984,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=0,tim=1359464472023678
BINDS #47953679205472:
Bind#0
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=03 fl2=1000000 frm=00 csi=00 siz=24 off=0
kxsbbbfp=2b9d16045340 bln=22 avl=02 flg=05
value=100
EXEC #47953679205472:c=2999,e=2765,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=3727996439,tim=1359464472026526
FETCH #47953679205472:c=3000,e=2883,p=0,cr=62,cu=0,mis=0,r=1,dep=0,og=1,plh=3727996439,tim=1359464472029485
STAT #47953679205472 id=1 cnt=1 pid=0 pos=1 obj=0 op='SORT AGGREGATE (cr=62 pr=0 pw=0 time=2884 us)'
STAT #47953679205472 id=2 cnt=9999 pid=1 pos=1 obj=25916 op='INDEX FAST FULL SCAN INX_TEST_ID (cr=62 pr=0 pw=0 time=2190 us cost=11 size=29997 card=9999)'
FETCH #47953679205472:c=0,e=2,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,plh=3727996439,tim=1359464472029832
PARSE #47953679348848:c=0,e=29,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=0,tim=1359464472030399
BINDS #47953679348848:
Bind#0
oacdty=123 mxl=4000(4000) mxlc=00 mal=00 scl=00 pre=00
oacflg=00 fl2=1000000 frm=00 csi=00 siz=4000 off=0
toid ptr value=A1E4A4A0 length=16
C7D9741553643AE0E0430100007F2FB7
kxsbbbfp=2b9d1605df70 bln=4000 avl=00 flg=15
Bind#1
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=01 fl2=1000000 frm=00 csi=00 siz=24 off=0
kxsbbbfp=2b9d1605f310 bln=22 avl=22 flg=05
value=###
An invalid number has been seen.Memory contents are :
Dump of memory from 0x00002B9D1605F310 to 0x00002B9D1605F326
2B9D1605F310 000010C1 00000000 00000000 00000000 [................]
2B9D1605F320 00000000 00000000 [........]
EXEC #47953679348848:c=0,e=393,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,plh=0,tim=1359464472030861
-- 跟踪当前会话
sys@MAA> grant execute on dbms_support to luocs;
Grant succeeded.
luocs@MAA> SELECT DBMS_SUPPORT.MYSID from DUAL;
SELECT DBMS_SUPPORT.MYSID from DUAL
*
ERROR at line 1:
ORA-00904: "DBMS_SUPPORT"."MYSID": invalid identifier
-- 这时候发现普通用户无法执行,我们需要如下授权
sys@MAA> grant execute on dbms_support to luocs;
Grant succeeded.
sys@MAA> CREATE PUBLIC SYNONYM dbms_support FOR dbms_support;
Synonym created.
luocs@MAA> SELECT DBMS_SUPPORT.MYSID from DUAL;
MYSID
----------
53
luocs@MAA> exec dbms_support.start_trace(waits=>true,binds=>false);
PL/SQL procedure successfully completed.
luocs@MAA> select count(*) from test;
COUNT(*)
----------
10000
luocs@MAA> exec dbms_support.stop_trace;
PL/SQL procedure successfully completed.
-- trace部分内容
=====================
PARSING IN CURSOR #47179837486632 len=25 dep=0 uid=51 oct=3 lid=51 tim=1359465350267384 hv=297253644 ad='9ed2c088' sqlid='7b2twsn8vgfsc'
select count(*) from test
END OF STMT
PARSE #47179837486632:c=0,e=144,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=1950795681,tim=1359465350267383
EXEC #47179837486632:c=0,e=57,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=1950795681,tim=1359465350267512
WAIT #47179837486632: nam='SQL*Net message to client' ela= 2 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=1359465350267576
FETCH #47179837486632:c=2000,e=1851,p=0,cr=37,cu=0,mis=0,r=1,dep=0,og=1,plh=1950795681,tim=1359465350269457
STAT #47179837486632 id=1 cnt=1 pid=0 pos=1 obj=0 op='SORT AGGREGATE (cr=37 pr=0 pw=0 time=1832 us)'
STAT #47179837486632 id=2 cnt=10000 pid=1 pos=1 obj=25886 op='TABLE ACCESS FULL TEST (cr=37 pr=0 pw=0 time=6947 us cost=12 size=0 card=10000)'
WAIT #47179837486632: nam='SQL*Net message from client' ela= 164 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=1359465350269784
FETCH #47179837486632:c=0,e=2,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,plh=1950795681,tim=1359465350269824
WAIT #47179837486632: nam='SQL*Net message to client' ela= 1 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=1359465350269849
WAIT #47179837486632: nam='SQL*Net message from client' ela= 458 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=1359465350270323
PARSE #47179837532376:c=0,e=29,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=0,tim=1359465350270400
WAIT #47179837532376: nam='SQL*Net message to client' ela= 1 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=1359465350270667
EXEC #47179837532376:c=0,e=239,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,plh=0,tim=1359465350270709
3、DBMS_MONITOR
DBMS_MONITOR是Oracle 从10g开始引入的程序包,它即可以实现传统的跟踪功能,也可以在拥有连接池或共享服务器等的多层平台中使用,请阅读下段文:
Oracle 10g offers a new package to allow sessions to be traced end to end in multi-tier architectures that share sessions using connection pooling or multi-threading. This package allows applications written using for instance JDBC / Java or something like Forte to be traced where it would normally be very difficult to identify a database session belonging to a client as the sessions / clients pairings change with time.
The new functionality works in three levels. You can use the old SID / SERIAL# pairings to identify a session but you can also use a client identifier or a service name / module / action to identify a client session to be traced. The package also offers a set of procedures to allow statistics to be gathered for the same groups. These statistics can then be selected from dynamic views.
下面就看一下我的演示:
-- 使用传统方式,通过SID和SERIAL#来跟踪会话
luocs@MAA> select sid, serial# from v$session where sid = (select sid from v$mystat where rownum=1);
SID SERIAL#
---------- ----------
53 21813
-- 启动跟踪
sys@MAA> exec DBMS_MONITOR.SESSION_TRACE_ENABLE(53,21813,true,true);
PL/SQL procedure successfully completed.
luocs@MAA> variable x number
luocs@MAA> exec :l := 1;
PL/SQL procedure successfully completed.
luocs@MAA> select count(*) from test where id=:l;
COUNT(*)
----------
1
-- 停止跟踪
sys@MAA> exec DBMS_MONITOR.SESSION_TRACE_DISABLE(53,21813);
PL/SQL procedure successfully completed.
TRACE内容略。
�C 当前会话跟踪
luocs@MAA> EXEC DBMS_MONITOR.session_trace_enable;
luocs@MAA> EXEC DBMS_MONITOR.session_trace_enable(waits=>TRUE, binds=>FALSE);
luocs@MAA> EXEC DBMS_MONITOR.session_trace_disable;
�C 另外,我们也可以使用客户端标识符来进行跟踪
下面是我一个使用例子
luocs@WWW> BEGIN
2 DBMS_SESSION.SET_IDENTIFIER('www.luocs.com');
3 DBMS_MONITOR.CLIENT_ID_TRACE_ENABLE
4 (CLIENT_ID => 'www.luocs.com',
5 WAITS => TRUE
6 );
7 END;
8 /
PL/SQL procedure successfully completed.
luocs@WWW> select /*+ parallel(3) */ count(*) from test1;
COUNT(*)
----------
456128
luocs@WWW> exec DBMS_MONITOR.CLIENT_ID_TRACE_DISABLE('www.luocs.com');
PL/SQL procedure successfully completed.
sys@WWW> select client_identifier from v$session where sid=(select sid from v$mystat where rownum=1);
CLIENT_IDENTIFIER
----------------------------------------------------------------------------------------------------
www.luocs.com
sys@WWW> col PRIMARY_ID for a30
sys@WWW> select trace_type, primary_id, waits, binds from dba_enabled_traces;
TRACE_TYPE PRIMARY_ID WAITS BINDS
------------------------------------------ ------------------------------ ---------- ----------
CLIENT_ID www.luocs.com TRUE FALSE
[oracle@rac1 ~]$ cd /u01/app/oracle/diag/rdbms/www/ltb1/trace/
[oracle@rac1 trace]$ trcsess clientid=www.luocs.com output=luocs_test2.trc
[oracle@rac1 trace]$ ls luocs_test2.trc
-rw-r--r-- 1 oracle oinstall 103514 Jan 27 07:06 luocs_test2.trc
-- trace内容略
关于DBMS_MONITOR更多更详尽的内容,请阅读官方NOTE PL/SQL Packages and Types Reference部分。
4、 DBMS_SESSION
DBMS_SESSION也有几个PL/SQL是和跟踪相关的,它们就是SESSION_TRACE_ENABLE/DISABLE、SET_SQL_TRACE,注意DBMS_SESSION只能跟踪当前会话,无法跟踪其他SESSION。
好,理论介绍还是减少点,请阅读官方NOTE。
下面是我的演示:
-- SESSION_TRACE_ENABLE/DISABLE过程可以设置等待和变量跟踪
luocs@MAA> exec DBMS_SESSION.SESSION_TRACE_ENABLE(TRUE,TRUE);
luocs@MAA> exec DBMS_SESSION.SESSION_TRACE_ENABLE(WAITS=>TRUE, BINDS=>TRUE);
luocs@MAA> variable x number
luocs@MAA> exec :l := 100
PL/SQL procedure successfully completed.
luocs@MAA> select count(*) from test where id=:l;
COUNT(*)
----------
9999
-- 停止跟踪
luocs@MAA> exec DBMS_SESSION.SESSION_TRACE_DISABLE();
-- trace内容略
-- SET_SQL_TRACE过程好比alter session set sql_trace=true|false
luocs@MAA> exec DBMS_SESSION.SET_SQL_TRACE(TRUE);
PL/SQL procedure successfully completed.
luocs@MAA> variable x number
luocs@MAA> exec :l := 100
PL/SQL procedure successfully completed.
luocs@MAA> select count(*) from test where id=:l;
COUNT(*)
----------
9999
luocs@MAA> exec DBMS_SESSION.SET_SQL_TRACE(FALSE);
PL/SQL procedure successfully completed.
-- trace内容里看不到绑定变量和等待的信息
5、ORADEBUG
ORADEBUG功能非常强大,我们执行oradebug help将会看到非常多的功能可使用,我也非常喜欢使用它,甚至有的时候10046、10053等events都是通过ORADEBUG来设置。ORADEBUG是SYS的工具,即使权限较大的SYSTEM用户都无法使用它:
system@MAA> show user
USER is "SYSTEM"
system@MAA> oradebug setmypid
ORA-01031: insufficient privileges
因此,oradebug只能跟踪SYS用户的当前SESSION,如下方式:
sys@MAA> oradebug setmypid
sys@MAA> oradebug unlimit
sys@MAA> oradebug event 10046 trace name context forever, level 12
sys@MAA> exec our code
sys@MAA> oradebug event 10046 trace name context off
sys@MAA> oradebug tracefile_name
/u01/app/oracle/diag/rdbms/maa/maa/trace/maa_ora_17641.trc
当然,我们通过oradebug非常方便地跟踪其他会话,如下方式:
luocs@MAA> 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);
PID SPID
---------- ------------------------------------------------
25 17678
-- 指定跟踪SESSION的SPID(OS process)
sys@MAA> oradebug setospid 17678
Oracle pid: 25, Unix process pid: 17678, image: [email protected] (TNS V1-V3)
-- 或者指定跟踪SESSION的PID(Oracle process ID)
sys@MAA> oradebug setorapid 25
Oracle pid: 25, Unix process pid: 17678, image: [email protected] (TNS V1-V3)
sys@MAA> oradebug unlimit
sys@MAA> oradebug event 10053 trace name context forever, level 1
sys@MAA> exec our code
sys@MAA> oradebug event 10053 trace name context off
sys@MAA> oradebug tracefile_name
以上五种方法,不要求DBA全会,在工作中选择自己喜欢的一两种方式,能够熟练使用即可。
另外,查看SQL TRACE还有DBA常用的AUTOTRACE(SQL*Plus)和10053 EVENTS(CBO trace)。
-- AUTOTRACE
luocs@MAA> set autotrace on
luocs@MAA> set autotrace on explain
luocs@MAA> set autotrace on statistics
luocs@MAA> set autotrace traceonly
luocs@MAA> set autotrace traceonly explain
luocs@MAA> set autotrace traceonly explain statistics
luocs@MAA> set autotrace off
我喜欢使用缩略方式,比如
luocs@MAA> set autot trace exp stat
-- 10053 EVENTS
luocs@MAA> alter session set events '10053 trace name context forever, level 1';
luocs@MAA> alter session set events '10053 trace name context off';
sys@MAA> oradebug event 10053 trace name context forever, level 1
sys@MAA> oradebug event 10053 trace name context off
oracle视频教程请关注:http://u.youku.com/user_video/id_UMzAzMjkxMjE2.html