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.

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章