SQL_TRACE使用小結
一、關於基礎表
Oracle 10G之前,啓用AUTOTRACE功能需要手工創建plan_table表,創建腳本爲$ORACLE_HOME/rdbms/admin/utlxplan.sql。但在10g中,已經默認創建了PLAN_TABLE$的基表,並以public用戶創建了相應的同義詞PUBLIC。
SQL> select owner,object_name,OBJECT_TYPE from dba_objects where object_name like '%PLAN_TABLE%';
OWNER OBJECT_NAME OBJECT_TYPE
------------------------------ -------------------- -------------------
SYS SQL_PLAN_TABLE_TYPE TYPE
PUBLIC SQL_PLAN_TABLE_TYPE SYNONYM
SYS PLAN_TABLE$ TABLE
PUBLIC PLAN_TABLE SYNONYM
EXFSYS EXF$PLAN_TABLE TABLE
SQL> select * from dba_synonyms where SYNONYM_NAME like '%PLAN_TABLE%';
OWNER SYNONYM_NAME TABLE_OWNER TABLE_NAME DB_LINK
-------------- ---------------------- ------------------------------ ------------------------------ --------
PUBLIC SQL_PLAN_TABLE_TYPE SYS SQL_PLAN_TABLE_TYPE
PUBLIC PLAN_TABLE SYS PLAN_TABLE$
從上面的結果可以看出,PLAN_TABLE正是基於PLAN_TABLE$的同義詞。
二、關於plustrace角色
和Oracle9i一樣,10g中plustrace角色默認也是disabled的。如果使用非授權用戶打開Oracle trace功能會得到以下的錯誤。
SQL> conn hr/hr
Connected.
SQL> set autotrace trace
SP2-0618: Cannot find the Session Identifier. Check PLUSTRACE role is enabled
SP2-0611: Error enabling STATISTICS report
這時需要執行$ORACLE_HOME/sqlplus/admin/plustrce.sql腳本,手工創建plustrace角色。
SQL> @$ORACLE_HOME/sqlplus/admin/plustrce.sql;
SQL>
SQL> drop role plustrace;
drop role plustrace
*
ERROR at line 1:
ORA-01919: role 'PLUSTRACE' does not exist
SQL> create role plustrace;
Role created.
SQL> grant select on v_$sesstat to plustrace;
Grant succeeded.
SQL> grant select on v_$statname to plustrace;
Grant succeeded.
SQL> grant select on v_$mystat to plustrace;
Grant succeeded.
SQL> grant plustrace to dba with admin option;
Grant succeeded.
SQL> set echo off
接下來就可以手工將plustrace角色授予需要的角色或用戶,或者直接將其授予public角色,這樣所有public角色的用戶都有使用autotrace功能的權限了。
SQL> grant plustrace to hr;
Grant succeeded.
SQL> conn hr/hr
Connected.
SQL> set autotrace trace
三、關於autotrace功能內部操作
默認的,在啓用autotrace功能時Oracle另啓用一個session,專門用於收集和輸出統計信息。
SQL> set autotrace off
SQL> select sid,serial#,username from v$session where username is not null;
SID SERIAL# USERNAME
---------- ---------- ------------------------------
146 906 SYS
159 3 SYS
......
SQL> set autotrace on exp
SQL> select sid,serial#,username from v$session where username is not null;
SID SERIAL# USERNAME
---------- ---------- ------------------------------
129 6 SYSMAN
135 4 DBSNMP
136 356 SYSMAN
143 45 SYSMAN
145 10 SYSMAN
146 906 SYS
149 38 DBSNMP
159 3 SYS
8 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3733760267
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 108 | 0 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 1 | 108 | 0 (0)| 00:00:01 |
|* 2 | FIXED TABLE FULL | X$KSUSE | 1 | 95 | 0 (0)| 00:00:01 |
|* 3 | FIXED TABLE FIXED INDEX| X$KSLED (ind:2) | 1 | 13 | 0 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("S"."KSUUDLNA" IS NOT NULL AND "S"."INST_ID"=USERENV('INSTANCE') AND
BITAND("S"."KSSPAFLG",1)<>0 AND BITAND("S"."KSUSEFLG",1)<>0)
3 - filter("S"."KSUSEOPC"="E"."INDX")
而收集統計信息的時候,則多出一個session。
SQL> set autotrace on stat
SQL> select sid,serial#,username from v$session where username is not null;
SID SERIAL# USERNAME
---------- ---------- ------------------------------
126 692 SYS
129 6 SYSMAN
135 4 DBSNMP
136 356 SYSMAN
143 45 SYSMAN
145 10 SYSMAN
146 906 SYS
149 38 DBSNMP
159 3 SYS
9 rows selected.
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
695 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
9 rows processed
SQL> select a.sid,a.serial#,a.username,b.pid,b.spid
2 from v$session a,v$process b
3 where a.paddr=b.addr and a.username is not null;
SID SERIAL# USERNAME PID SPID
---------- ---------- ------------------------------ ---------- ------------
159 3 SYS 15 4261
146 906 SYS 18 6977
126 692 SYS 18 6977
......
9 rows selected.
$ ps -ef|grep -v grep|grep 6977
oracle 6977 6976 0 21:22 ? 00:00:00 oraclerandy (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
四、關於DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION
其實我們更多的時候需要跟蹤的其他用戶的進程,而很多這樣的用戶可能沒有被授予或者不允許授予plustrace角色。這時可以使用DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION過程來實現對進程的跟蹤,該過程需要提供用戶進程的sid和serial#。
SQL> select sid,serial# from v$session where username ='HR';
SID SERIAL#
---------- ----------
159 5
SQL> exec dbms_system.SET_SQL_TRACE_IN_SESSION(159,5,true);
PL/SQL procedure successfully completed.
SQL> select a.sid,a.serial#,a.username,b.pid,b.spid
2 from v$session a,v$process b
3 where a.paddr=b.addr and a.username='HR';
SID SERIAL# USERNAME PID SPID
---------- ---------- ------------------------------ ---------- ------------
159 5 HR 15 9080
回到用戶HR的連接中執行SQL語句,然後使用tkprof工具格式化USER_DUMP_FILE目錄中的跟蹤文件。
$ tkprof randy_ora_9080.trc 9080.txt
$ more 9080.txt
......
select *
from
jobs
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 2 0.01 0.02 0 0 0 0
Execute 2 0.00 0.00 0 0 0 0
Fetch 6 0.00 0.04 6 18 0 38
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 10 0.02 0.06 6 18 0 38
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 55
Rows Row Source Operation
------- ---------------------------------------------------
19 TABLE ACCESS FULL JOBS (cr=9 pr=6 pw=0 time=42771 us)
......
從跟蹤文件中,可以發現很多關於Oracle在實現用戶需求時的內部操作,深入研究確實會有很多的收穫。不過這裏我們關心的是上面摘錄的部分,可以看到select * from jobs執行計劃和相關的統計信息。
五、使用會話級10046事件
除了上述的方法外,還可以使用會話級的10046事件來實現進程跟蹤。
SQL> alter session set events '10046 trace name context forever, level 12';
SQL> alter session set events '10046 trace name context off';
如果用戶沒有alter session的權限,可以使用DBMS_SYSTEM.SET_EV過程來實現對用戶進程的跟蹤。
SQL> desc DBMS_SYSTEM
......
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
......
幾個參數分別是進程sid,serial#,event name,level,username。
SQL> select sid,serial# from v$session where username ='HR';
SID SERIAL#
---------- ----------
154 298
SQL> exec dbms_system.set_ev(154,298,10046,12,'');
PL/SQL procedure successfully completed.
SQL> select a.sid,a.serial#,a.username,b.pid,b.spid
2 from v$session a,v$process b
3 where a.paddr=b.addr and a.username='HR';
SID SERIAL# USERNAME PID SPID
---------- ---------- ------------------------------ ---------- ------------
154 298 HR 15 9903
使用tkprof格式化跟蹤文件,可以得到和第四部分相同的輸出。
六、使用DBMS_MONITOR
DBMS_MONITOR包也非常的強大,可以提供基於客戶ID、服務模塊以及數據庫級和會話級的跟蹤和統計。這裏使用SESSION_TRACE_ENABLE來實現數據庫級的跟蹤。
SQL> desc dbms_monitor
......
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
......
SQL> select a.sid,a.serial#,a.username,b.pid,b.spid
2 from v$session a,v$process b
3 where a.paddr=b.addr and a.username = 'HR';
SID SERIAL# USERNAME PID SPID
---------- ---------- ------------------------------ ---------- ------------
159 348 HR 18 12569
SQL> exec dbms_monitor.SESSION_TRACE_ENABLE(159,348);
PL/SQL procedure successfully completed.
SQL> exec dbms_monitor.SESSION_TRACE_DISABLE(159,348);
PL/SQL procedure successfully completed.
使用這種方法也可以實現對會話的跟蹤。
七、使用oradebug實現跟蹤
oradebug是一個非常強大的工具,廣泛的使用在設置debug事件和產生dumps。我們也可以通過這個工具,設置會話的10046事件,從而實現對會話的跟蹤。說到底,還是10046事件的一種實現方式,但是由於它強大的功能本人對它非常的鐘愛,所以單獨列了出來。
接上面的實驗,我們可以看到用戶HR的PID爲18,下面我們通過oradebug實現對該進程的跟蹤。
SQL> oradebug SETORAPID 18
Unix process pid: 12569, image: oracle@oracle (TNS V1-V3)
SQL> oradebug SESSION_EVENT 10046 trace name context forever,level 12;
Statement processed.
SQL> oradebug tracefile_name
/u01/oracle/admin/randy/udump/randy_ora_12569.trc
SQL> oradebug SESSION_EVENT 10046 trace name context off;
Statement processed.
Oracle 10G之前,啓用AUTOTRACE功能需要手工創建plan_table表,創建腳本爲$ORACLE_HOME/rdbms/admin/utlxplan.sql。但在10g中,已經默認創建了PLAN_TABLE$的基表,並以public用戶創建了相應的同義詞PUBLIC。
SQL> select owner,object_name,OBJECT_TYPE from dba_objects where object_name like '%PLAN_TABLE%';
OWNER OBJECT_NAME OBJECT_TYPE
------------------------------ -------------------- -------------------
SYS SQL_PLAN_TABLE_TYPE TYPE
PUBLIC SQL_PLAN_TABLE_TYPE SYNONYM
SYS PLAN_TABLE$ TABLE
PUBLIC PLAN_TABLE SYNONYM
EXFSYS EXF$PLAN_TABLE TABLE
SQL> select * from dba_synonyms where SYNONYM_NAME like '%PLAN_TABLE%';
OWNER SYNONYM_NAME TABLE_OWNER TABLE_NAME DB_LINK
-------------- ---------------------- ------------------------------ ------------------------------ --------
PUBLIC SQL_PLAN_TABLE_TYPE SYS SQL_PLAN_TABLE_TYPE
PUBLIC PLAN_TABLE SYS PLAN_TABLE$
從上面的結果可以看出,PLAN_TABLE正是基於PLAN_TABLE$的同義詞。
二、關於plustrace角色
和Oracle9i一樣,10g中plustrace角色默認也是disabled的。如果使用非授權用戶打開Oracle trace功能會得到以下的錯誤。
SQL> conn hr/hr
Connected.
SQL> set autotrace trace
SP2-0618: Cannot find the Session Identifier. Check PLUSTRACE role is enabled
SP2-0611: Error enabling STATISTICS report
這時需要執行$ORACLE_HOME/sqlplus/admin/plustrce.sql腳本,手工創建plustrace角色。
SQL> @$ORACLE_HOME/sqlplus/admin/plustrce.sql;
SQL>
SQL> drop role plustrace;
drop role plustrace
*
ERROR at line 1:
ORA-01919: role 'PLUSTRACE' does not exist
SQL> create role plustrace;
Role created.
SQL> grant select on v_$sesstat to plustrace;
Grant succeeded.
SQL> grant select on v_$statname to plustrace;
Grant succeeded.
SQL> grant select on v_$mystat to plustrace;
Grant succeeded.
SQL> grant plustrace to dba with admin option;
Grant succeeded.
SQL> set echo off
接下來就可以手工將plustrace角色授予需要的角色或用戶,或者直接將其授予public角色,這樣所有public角色的用戶都有使用autotrace功能的權限了。
SQL> grant plustrace to hr;
Grant succeeded.
SQL> conn hr/hr
Connected.
SQL> set autotrace trace
三、關於autotrace功能內部操作
默認的,在啓用autotrace功能時Oracle另啓用一個session,專門用於收集和輸出統計信息。
SQL> set autotrace off
SQL> select sid,serial#,username from v$session where username is not null;
SID SERIAL# USERNAME
---------- ---------- ------------------------------
146 906 SYS
159 3 SYS
......
SQL> set autotrace on exp
SQL> select sid,serial#,username from v$session where username is not null;
SID SERIAL# USERNAME
---------- ---------- ------------------------------
129 6 SYSMAN
135 4 DBSNMP
136 356 SYSMAN
143 45 SYSMAN
145 10 SYSMAN
146 906 SYS
149 38 DBSNMP
159 3 SYS
8 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3733760267
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 108 | 0 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 1 | 108 | 0 (0)| 00:00:01 |
|* 2 | FIXED TABLE FULL | X$KSUSE | 1 | 95 | 0 (0)| 00:00:01 |
|* 3 | FIXED TABLE FIXED INDEX| X$KSLED (ind:2) | 1 | 13 | 0 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("S"."KSUUDLNA" IS NOT NULL AND "S"."INST_ID"=USERENV('INSTANCE') AND
BITAND("S"."KSSPAFLG",1)<>0 AND BITAND("S"."KSUSEFLG",1)<>0)
3 - filter("S"."KSUSEOPC"="E"."INDX")
而收集統計信息的時候,則多出一個session。
SQL> set autotrace on stat
SQL> select sid,serial#,username from v$session where username is not null;
SID SERIAL# USERNAME
---------- ---------- ------------------------------
126 692 SYS
129 6 SYSMAN
135 4 DBSNMP
136 356 SYSMAN
143 45 SYSMAN
145 10 SYSMAN
146 906 SYS
149 38 DBSNMP
159 3 SYS
9 rows selected.
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
695 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
9 rows processed
SQL> select a.sid,a.serial#,a.username,b.pid,b.spid
2 from v$session a,v$process b
3 where a.paddr=b.addr and a.username is not null;
SID SERIAL# USERNAME PID SPID
---------- ---------- ------------------------------ ---------- ------------
159 3 SYS 15 4261
146 906 SYS 18 6977
126 692 SYS 18 6977
......
9 rows selected.
$ ps -ef|grep -v grep|grep 6977
oracle 6977 6976 0 21:22 ? 00:00:00 oraclerandy (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
四、關於DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION
其實我們更多的時候需要跟蹤的其他用戶的進程,而很多這樣的用戶可能沒有被授予或者不允許授予plustrace角色。這時可以使用DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION過程來實現對進程的跟蹤,該過程需要提供用戶進程的sid和serial#。
SQL> select sid,serial# from v$session where username ='HR';
SID SERIAL#
---------- ----------
159 5
SQL> exec dbms_system.SET_SQL_TRACE_IN_SESSION(159,5,true);
PL/SQL procedure successfully completed.
SQL> select a.sid,a.serial#,a.username,b.pid,b.spid
2 from v$session a,v$process b
3 where a.paddr=b.addr and a.username='HR';
SID SERIAL# USERNAME PID SPID
---------- ---------- ------------------------------ ---------- ------------
159 5 HR 15 9080
回到用戶HR的連接中執行SQL語句,然後使用tkprof工具格式化USER_DUMP_FILE目錄中的跟蹤文件。
$ tkprof randy_ora_9080.trc 9080.txt
$ more 9080.txt
......
select *
from
jobs
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 2 0.01 0.02 0 0 0 0
Execute 2 0.00 0.00 0 0 0 0
Fetch 6 0.00 0.04 6 18 0 38
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 10 0.02 0.06 6 18 0 38
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 55
Rows Row Source Operation
------- ---------------------------------------------------
19 TABLE ACCESS FULL JOBS (cr=9 pr=6 pw=0 time=42771 us)
......
從跟蹤文件中,可以發現很多關於Oracle在實現用戶需求時的內部操作,深入研究確實會有很多的收穫。不過這裏我們關心的是上面摘錄的部分,可以看到select * from jobs執行計劃和相關的統計信息。
五、使用會話級10046事件
除了上述的方法外,還可以使用會話級的10046事件來實現進程跟蹤。
SQL> alter session set events '10046 trace name context forever, level 12';
SQL> alter session set events '10046 trace name context off';
如果用戶沒有alter session的權限,可以使用DBMS_SYSTEM.SET_EV過程來實現對用戶進程的跟蹤。
SQL> desc DBMS_SYSTEM
......
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
......
幾個參數分別是進程sid,serial#,event name,level,username。
SQL> select sid,serial# from v$session where username ='HR';
SID SERIAL#
---------- ----------
154 298
SQL> exec dbms_system.set_ev(154,298,10046,12,'');
PL/SQL procedure successfully completed.
SQL> select a.sid,a.serial#,a.username,b.pid,b.spid
2 from v$session a,v$process b
3 where a.paddr=b.addr and a.username='HR';
SID SERIAL# USERNAME PID SPID
---------- ---------- ------------------------------ ---------- ------------
154 298 HR 15 9903
使用tkprof格式化跟蹤文件,可以得到和第四部分相同的輸出。
六、使用DBMS_MONITOR
DBMS_MONITOR包也非常的強大,可以提供基於客戶ID、服務模塊以及數據庫級和會話級的跟蹤和統計。這裏使用SESSION_TRACE_ENABLE來實現數據庫級的跟蹤。
SQL> desc dbms_monitor
......
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
......
SQL> select a.sid,a.serial#,a.username,b.pid,b.spid
2 from v$session a,v$process b
3 where a.paddr=b.addr and a.username = 'HR';
SID SERIAL# USERNAME PID SPID
---------- ---------- ------------------------------ ---------- ------------
159 348 HR 18 12569
SQL> exec dbms_monitor.SESSION_TRACE_ENABLE(159,348);
PL/SQL procedure successfully completed.
SQL> exec dbms_monitor.SESSION_TRACE_DISABLE(159,348);
PL/SQL procedure successfully completed.
使用這種方法也可以實現對會話的跟蹤。
七、使用oradebug實現跟蹤
oradebug是一個非常強大的工具,廣泛的使用在設置debug事件和產生dumps。我們也可以通過這個工具,設置會話的10046事件,從而實現對會話的跟蹤。說到底,還是10046事件的一種實現方式,但是由於它強大的功能本人對它非常的鐘愛,所以單獨列了出來。
接上面的實驗,我們可以看到用戶HR的PID爲18,下面我們通過oradebug實現對該進程的跟蹤。
SQL> oradebug SETORAPID 18
Unix process pid: 12569, image: oracle@oracle (TNS V1-V3)
SQL> oradebug SESSION_EVENT 10046 trace name context forever,level 12;
Statement processed.
SQL> oradebug tracefile_name
/u01/oracle/admin/randy/udump/randy_ora_12569.trc
SQL> oradebug SESSION_EVENT 10046 trace name context off;
Statement processed.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.