10046 trace的跟蹤等級
原網址:http://blog.csdn.net/miyatang/article/details/8075785
10046是一個Oracle的內部事件(event),通過設置這個事件可以得到Oracle內部執行系統解析、調用、等待、綁定變量等詳細的trace信息,對於分析系統的性能有着非常重要的作用。
設置10046事件的不同級別能得到不同詳細程度的trace信息,下面就列出各個不同級別的對應作用:
等級 | 二進制 | 作用 |
---|---|---|
0 | 0000 | 無輸出 |
1 | 0001 | 輸出 ****,APPNAME(應用程序名),PARSING IN CURSOR,PARSE ERROR(SQL解析),EXEC(執行),FETCH(獲取數據),UNMAP,SORT UNMAP(排序,臨時段),ERROR,STAT(執行計劃),XCTEND(事務)等行 |
2 | 0011 | 與等級1完全一樣 |
4 | 0101 | 包括等級1的輸出,加上BIND行(綁定變量信息) |
8 | 1001 | 包括等級1的輸出,加上WAIT行(等待事件信息) |
12 | 1101 | 輸出等級1、等級4以及等級8的所有信息 |
等級1的10046 trace被視爲是普通的SQL Trace,而等級4、等級8以及等級12則被稱爲Extended SQL Trace,Extended SQL Trace裏面包括了最有用的WAIT信息,因此在實際中也是用的最多的。
與SQL Trace相關的參數
在打開10046時間的SQL Trace之前,要先設置好下面幾個參數。
timed_statistics
這個參數決定了是否收集與時間相關的統計信息,如果這個參數爲FALSE的話,那麼SQL Trace的結果基本沒有多大的用處,默認情況下這個參數設置爲TRUE。
max_dump_file_size
dump文件的大小,也就是決定是否限制SQL Trace文件的大小,在一個很忙的系統上面做SQL Trace的話可能會生成很多的信息,因此最好在會話級別將這個參數設置成unlimited。
tracefile_identifier
給Trace文件設置識別字符串,這是個非常有用的參數,設置一個易讀的字串能更快的找到Trace文件。
要在當前會話修改上述參數很簡單,只要使用下面的命令即可:
1 2 3 | ALTER SESSION SET timed_statistics= true ALTER SESSION SET max_dump_file_size=unlimited ALTER SESSION SET tracefile_identifier='my_trace_session |
當然,這些參數可以在系統級別修改的,也可以加載init文件中或是spfile中,讓系統啓動時自動做全局設置。
要是在系統運行時動態的修改別的會話的這些參數就需要藉助DBMS_SYSTEM這個包了,設置方法如下:
1 2 3 4 5 6 7 8 9 | SYS.DBMS_SYSTEM.SET_BOOL_PARAM_IN_SESSION( :sid, :serial, 'timed_statistics' , true ) SYS.DBMS_SYSTEM.SET_INT_PARAM_IN_SESSION( :sid, :serial, 'max_dump_file_size' , 2147483647 ) |
注意,Oracle並沒有提供一個set_string_param_in_session的函數在dbms_system包中,因此tracefile_identifier是無法在別的會話中修改的(至少我到現在沒有找到一個可以設置的方法)。
10046 Trace啓動方法
開啓當前會話的10046 Trace
使用sql_trace參數
sql_trace應該是簡單快捷的開啓Trace的方法了,不過通過sql_trace只能開啓級別爲1的Trace,而無法開啓其他更高級的Trace。
1 2 3 4 5 | -- 開啓Trace ALTER SESSION SET sql_trace= true ; -- 關閉Trace ALTER SESSION SET sql_trace= false ; |
使用set event開啓Trace
使用set event打開10046事件Trace是最常用的了。
1 2 3 4 5 | -- 開啓級別爲12的Trace,level後面的數字設置了Trace的級別 ALTER SESSION SET EVENTS '10046 trace name context forever, level 12' -- 關閉Trace,任何級別 ALTER SESSION SET EVENTS '10046 trace name context off' |
開啓其他會話的10046 Trace
使用登陸觸發器開啓Trace
我們可以通過編寫登陸觸發器來開啓10046 Trace,使用這種方法開啓Trace的代碼和開啓當前會話的是一樣的,不同的就是這些開啓代碼是包含在一個after logon觸發器裏面的。
1 2 3 4 5 6 7 8 9 10 | -- 代碼來自《Optimazing Oracle Performance》 P116 CREATE OR REPLACE TRIGGER trace_test_user AFTER LOGON ON DATABASE BEGIN IF USER LIKE '%\_test' ESCAPE '\' THEN EXECUTE IMMEDIATE ' ALTER SESSION SET timed_statistics= true '; EXECUTE IMMEDIATE ' ALTER SESSION SET max_dump_file_size=unlimited '; EXECUTE IMMEDIATE ' ALTER SESSION SET EVENTS '' 10046 trace name context forever, level 8 '' '; END IF; END ; / |
使用oradebug工具
使用oradebug工具必須要知道所要處理的進程的OS進程PID,OS PID可以使用下面的語句得到:
1 2 3 4 5 6 | SELECT S.USERNAME, P.SPID OS_PROCESS_ID, P.PID ORACLE_PROCESS_ID FROM V$SESSION S, V$PROCESS P WHERE S.PADDR = P.ADDR AND S.USERNAME = UPPER ( '&USER_NAME' ); |
得到PID之後就可以使用oradebug工具了,注意需要使用sysdba登陸到數據庫:
1 2 3 4 5 6 7 8 | -- 假設9999爲會話的OS PID oradebug setospid 9999; -- 設置Trace文件大小 oradebug unlimit; -- 開啓級別爲12的Trace oradebug event 10046 trace name context forever , level 12; --關閉trace Oradebug event 10046 trace name context off ; |
使用DBMS_SYSTEM包
DBMS_SYSTEM包提供了兩個開啓10046 Trace的方法,一個是使用SET_SQL_TRACE_IN_SESSION過程,不過使用這個過程的效果和sql_trace是一樣的:
1 2 3 4 5 | -- 開啓Trace EXEC SYS.DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION(:sid, :serial#, true ); -- 關閉Trace EXEC SYS.DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION(:sid, :serial#, false ); |
另一個方法是使用SET_EV過程,當然這個過程不僅僅用來設置10046事件,還能設置所有的其他的事件,使用方法爲:
1 2 3 4 5 6 7 8 | PROCEDURE SET_EV Argument Name Type In / Out Default ? ------------------------------ ----------------------- ------ -------- SI BINARY_INTEGER IN SE BINARY_INTEGER IN EV BINARY_INTEGER IN LE BINARY_INTEGER IN NM VARCHAR2 IN |
使用例子:
1 2 3 4 5 | -- 開啓level 12的Trace EXEC SYS.DBMS_SYSTEM.SET_EV(:sid, :serial, 10046, 12, '' ); -- 關閉Trace EXEC SYS.DBMS_SYSTEM.SET_EV(:sid, :serial, 10046, 0, '' ); |
使用DBMS_SUPPORT包
DBMS_SUPPORT包默認情況下並沒有包含在數據庫中,需要通過運行$ORACLE_HOME/rdbms/admin/dbmssupp.sql安裝之後才能使用。
可以DBMS_SUPPORT包來開啓自身進程或者是別的進程的Trace。
開啓自身進程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | -- 使用方法 DESC DBMS_SUPPORT PROCEDURE START_TRACE Argument Name Type In / Out Default ? ------------------------------ ----------------------- ------ -------- WAITS BOOLEAN IN DEFAULT BINDS BOOLEAN IN DEFAULT PROCEDURE STOP_TRACE -- 實例 -- 開啓級別爲12的Trace EXEC SYS.DBMS_SUPPORT.START_TRACE( true , true ); -- 關閉Trace EXEC SYS.DBMS_SUPPORT.STOP_TRACE(); |
開啓其他進程的Trace:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | -- 使用方法 PROCEDURE START_TRACE_IN_SESSION Argument Name Type In / Out Default ? ------------------------------ ----------------------- ------ -------- SID NUMBER IN SERIAL NUMBER IN WAITS BOOLEAN IN DEFAULT BINDS BOOLEAN IN DEFAULT PROCEDURE STOP_TRACE_IN_SESSION Argument Name Type In / Out Default ? ------------------------------ ----------------------- ------ -------- SID NUMBER IN SERIAL NUMBER IN -- 實例 -- 開啓級別爲12的Trace EXEC SYS.DBMS_SUPPORT.START_TRACE_IN_SESSION(:sid, :serial, true , true ); -- 關閉Trace EXEC SYS.DBMS_SUPPORT.STOP_TRACE_IN_SESSION(:sid, :serial); |
使用DBMS_MONITOR包
Oracle 10g中DBMS_MONITOR包的出現改變了以往一次只能開啓一個會話的歷史,開啓了一個批量啓用10046 Trace的新紀元。
追蹤單個會話
首先看看與前面類似的開啓單個會話的Trace的方法,這個時候與DBMS_SUPPORT包是幾乎沒有區別的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | -- 過程定義 PROCEDURE SESSION_TRACE_DISABLE Argument Name Type In / Out Default ? ------------------------------ ----------------------- ------ -------- SESSION_ID BINARY_INTEGER IN DEFAULT SERIAL_NUM BINARY_INTEGER IN DEFAULT PROCEDURE SESSION_TRACE_ENABLE Argument Name Type In / Out Default ? ------------------------------ ----------------------- ------ -------- SESSION_ID BINARY_INTEGER IN DEFAULT SERIAL_NUM BINARY_INTEGER IN DEFAULT WAITS BOOLEAN IN DEFAULT BINDS BOOLEAN IN DEFAULT PLAN_STAT VARCHAR2 IN DEFAULT -- 實例 -- 開啓級別爲12的Trace,當前會話 EXEC DBMS_MONITOR.SESSION_TRACE_ENABLE(WAITS=> true ,BINDS=> true ); -- 開啓級別爲12的Trace,其他會話 EXEC DBMS_MONITOR.SESSION_TRACE_ENABLE(:sid, :serial, true , true ); -- 關閉Trace,當前會話 EXEC DBMS_MONITOR.SESSION_TRACE_DISABLE(); -- 關閉Trace,其他會話 EXEC DBMS_MONITOR.SESSION_TRACE_DISABLE(:sid, :serial); |
根據Client Identifier追蹤
使用DBMS_MONITOR包也許同根據client identifier來Trace多個不同的會話,client identifier可以通過V$SESSION裏面client_identifier字段看到,使用方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | -- 找出要Trace的client_identifier信息 SQL> SELECT sid, program, client_identifier FROM V$SESSION; SID PROGRAM CLIENT_IDENTIFIER ---------- ------------------------------------------------ ---------------------------------------- 71 [email protected] (TNS V1-V3) [email protected] 72 [email protected] (TNS V1-V3) [email protected] 75 [email protected] (TNS V1-V3) [email protected] -- 假設要Trace client_identifier是“[email protected]”的所有會話 -- 使用下面的語句即可,開啓一個level 12的Trace PL/SQL procedure successfully completed. -- 使用下面語句停止 |
根據Service, Module和Action追蹤
DBMS_MONITOR包的SERV_MOD_ACT_TRACE_ENABLE過程用來根據Service, Module和Action三個屬性開啓多個會話的Trace。
在進行Trace之前要確保你的應用程序設置了這三個相應的屬性,Oracle提供了包DBMS_APPLICATION_INFO用來設置module、action等信息,使用方法如下:
1 2 3 | EXEC dbms_application_info.SET_MODULE( 'Trace Test' , 'No Trace' ); EXEC DBMS_APPLICATION_INFO.SET_ACTION( '' No Trace '); EXEC DBMS_APPLICATION_INFO.SET_CLIENT_INFO(' A Haaaa'); |
設置完成之後我們就可以在V$SESSION看到這些信息了:
1 2 3 4 5 6 7 8 9 10 11 | SQL> COL ACTION FOR A10 SQL> COL MODULE FOR A45 SQL> COL SERVICE_NAME FOR A12 SQL> COL SID FOR 999 SQL> SELECT SID , service_name, module, action FROM v$session WHERE TYPE<> 'BACKGROUND' ; SID SERVICE_NAME MODULE ACTION ---- ------------ --------------------------------------------- ---------- 67 SYS$USERS SQL Developer 71 SYS$USERS [email protected] (TNS V1-V3) 72 SYS$USERS Trace Test No Trace |
知道了相應的信息再使用DBMS_MONITOR.SERV_MOD_ACT_TRACE_ENABLE來啓用對相應會話的Trace:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | -- 針對service name爲“SYS$USERS”的所有會話開啓Trace EXECUTE DBMS_MONITOR.SERV_MOD_ACT_TRACE_ENABLE(service_name => 'SYS$USERS' , waits => TRUE , binds => FALSE ); -- 停止所開啓的Trace EXECUTE DBMS_MONITOR.SERV_MOD_ACT_TRACE_DISABLE(service_name => 'SYS$USERS' ); -- 針對特定的action開啓Trace EXECUTE DBMS_MONITOR.SERV_MOD_ACT_TRACE_ENABLE(service_name=> 'SYS$USERS' , module_name=> 'Trace Test' , action_name => 'Trace' , waits => TRUE , binds => FALSE ); -- 停止所開啓的Trace EXECUTE DBMS_MONITOR.SERV_MOD_ACT_TRACE_DISABLE(service_name=> 'SYS$USERS' , module_name=> 'Trace Test' , action_name => 'Trace' ) |
開啓數據庫級的Trace
DBMS_MONITOR還能開啓數據庫級別的Trace。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | -- 定義 PROCEDURE DATABASE_TRACE_DISABLE Argument Name Type In / Out Default ? ------------------------------ ----------------------- ------ -------- INSTANCE_NAME VARCHAR2 IN DEFAULT PROCEDURE DATABASE_TRACE_ENABLE Argument Name Type In / Out Default ? ------------------------------ ----------------------- ------ -------- WAITS BOOLEAN IN DEFAULT BINDS BOOLEAN IN DEFAULT INSTANCE_NAME VARCHAR2 IN DEFAULT PLAN_STAT VARCHAR2 IN DEFAULT -- 開啓數據庫級的level 12的Trace EXEC DBMS_MONITOR.DATABASE_TRACE_ENABLE( true , true ); -- 停止數據庫級的Trace EXEC DBMS_MONITOR.DATABASE_TRACE_DISABLE(); |
這個功能影響整個數據庫,很強大,慎用!
開啓多個會話Trace的注意點
使用DBMS_MONITOR開啓多個會話的Trace是動態的,比如說當你要追蹤某個特定的action的Trace的時候,你並不需要先確定那個特定的action對應的會話正在運行中才能開啓相應的Trace,相反的是一旦某個進程的action滿足當前開啓的Trace的條件的時候,那個會話就會開始輸出Trace信息,當會話的action發生改變之後,Trace信息也會停止輸出,下面是一個簡單的測試。
先在一個進程中開始針對module爲“Trace Test”,action爲“Trace”的Trace:
1 2 3 4 5 6 | SQL> EXECUTE DBMS_MONITOR.SERV_MOD_ACT_TRACE_ENABLE(service_name=> 'SYS$USERS' , module_name=> 'Trace Test' , action_name => 'Trace' , waits => TRUE , binds => FALSE ); PL/SQL procedure successfully completed. |
然後在另外一個進程中執行下面的一序列語句:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | -- 設置當前會話的module和action SQL> EXEC DBMS_APPLICATION_INFO.SET_MODULE( 'Trace Test' , 'Trace' ); PL/SQL procedure successfully completed. -- 執行一個簡單的查詢 SQL> select 'trace' from dual; TRACE ------ trace -- 改變當前會話的action SQL> EXEC DBMS_APPLICATION_INFO.SET_MODULE( 'Trace Test' , 'No Trace' ); PL/SQL procedure successfully completed. -- 再執行另一個查詢 SQL> select 'no trace' from dual; NOTRACE -------- no trace |
執行完畢之後打開Trace文件就會發現第一次執行module、action設置的語句和第二次執行的“select ‘no trace’ from dual;”都沒有出現在Trace文件,Trace文件內容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | Unix process pid: 8900, image: [email protected] (TNS V1-V3) *** 2010-04-13 06:55:24.247 *** SESSION ID:(72.604) 2010-04-13 06:55:24.247 *** CLIENT ID:([email protected]) 2010-04-13 06:55:24.247 *** SERVICE NAME:(SYS$USERS) 2010-04-13 06:55:24.247 *** MODULE NAME:(Trace Test) 2010-04-13 06:55:24.247 *** ACTION NAME:(Trace) 2010-04-13 06:55:24.247 ===================== PARSING IN CURSOR #1 len=69 dep=0 uid=0 oct=47 lid=0 tim=1271141724247208 hv=297401484 ad='9eb182c8' sqlid='1ckkjdn8vmz4c' BEGIN DBMS_APPLICATION_INFO.SET_MODULE('Trace Test', 'Trace'); END; END OF STMT EXEC #1:c=0,e=113,p=0,cr=0,cu=0,mis=1,r=1,dep=0,og=1,plh=0,tim=1271141724247201 WAIT #1: nam='SQL*Net message to client' ela= 6 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=1271141724247735 *** 2010-04-13 06:55:32.913 WAIT #1: nam='SQL*Net message from client' ela= 8666025 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=1271141732913790 CLOSE #1:c=0,e=43,dep=0,type=0,tim=1271141732913937 ===================== PARSING IN CURSOR #2 len=25 dep=0 uid=0 oct=3 lid=0 tim=1271141732932795 hv=660028772 ad='9eb12b10' sqlid='70t5xg4mpfgb4' select 'trace ' from dual END OF STMT PARSE #2:c=1000,e=18805,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=1388734953,tim=1271141732932792 EXEC #2:c=0,e=47,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=1388734953,tim=1271141732932946 WAIT #2: nam='SQL*Net message to client' ela= 4 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=1271141732932989 FETCH #2:c=0,e=17,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,plh=1388734953,tim=1271141732933035 STAT #2 id=1 cnt=1 pid=0 pos=1 obj=0 op='FAST DUAL (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)' WAIT #2: nam='SQL*Net message from client' ela= 151 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=1271141732933287 FETCH #2:c=0,e=3,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,plh=1388734953,tim=1271141732933331 WAIT #2: nam='SQL*Net message to client' ela= 2 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=1271141732933364 *** 2010-04-13 06:55:48.413 WAIT #2: nam='SQL*Net message from client' ela= 15480453 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=1271141748413833 CLOSE #2:c=0,e=26,dep=0,type=0,tim=1271141748413963 ===================== PARSING IN CURSOR #1 len=72 dep=0 uid=0 oct=47 lid=0 tim=1271141748415935 hv=2176830839 ad='9eb0ec80' sqlid='ar765n60vzmbr' BEGIN DBMS_APPLICATION_INFO.SET_MODULE('Trace Test', 'No Trace'); END; END OF STMT PARSE #1:c=1999,e=1919,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=0,tim=1271141748415932 *** MODULE NAME:(Trace Test) 2010-04-13 06:55:48.416 *** ACTION NAME:(No Trace) 2010-04-13 06:55:48.416 EXEC #1:c=0,e=93,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,plh=0,tim=1271141748416134 |