基於以前開發的一個用於監控線程的CPU使用狀況的小工具TopShow我開發了一個用於追蹤Oracle內部函數調用的追蹤器——OraTracer 你可以用該工具追蹤監控Oracle多個內部函數的調用情況還可以嘗試探測函數的輸入參數的值也可以打印追蹤點被觸發時的調用堆棧追蹤可以設置在整個Oracle進程的級別也可以設置在某個線程以追蹤特定的會話
例子
捕獲oracle整個實例中被執行的SQL語句
首先在與可執行文件相同的目錄下設置追蹤點文件TracePointstxt內容如下
_opiprs *
_rpisplu *
_kprbprs
與函數名用空格相隔的數值為探測的參數數量如果再加上*N則表示嘗試將雙字節數字作為指針對待遞歸獲取其執行的值後面的數字為遞歸深度例如對於第一個追蹤點函數名為_opiprs探測個參數遞歸探測指針數據的深度為
注意#為注釋符
然後從進程列表中選擇ORACLEEXE不要選擇任何線程
最後點擊Trace按鈕一旦有語句被上述函數調用你就可以從監控窗口看到這些語句
SQL代碼
…
[ ::]User call: _rpisplu (TID: )
[Args()]:
select privilege#level from sysauth$ connect by grantee#=prior privilege# and privilege#> start with grantee#=: and privilege#>
×(=>NULL)
[ ::]User call: _rpisplu (TID: )
[Args()]:
alter session set NLS_LANGUAGE=AMERICAN NLS_TERRITORY=AMERICA NLS_CURRENCY=$ NLS_ISO_CURRENCY=AMERICA NLS_NUMERIC_CHARACTERS= NLS_DATE_FORMAT=DDMONRR NLS_DATE_LANGUAGE=AMERICAN NLS_SORT=BINARY
xd(=>NULL)
[ ::]User call: _opiprs (TID: )
[Args()]:
×cce(=>×)
alter session set NLS_LANGUAGE=AMERICAN NLS_TERRITORY=AMERICA NLS_CURRENCY=$ NLS_ISO_CURRENCY=AMERICA NLS_NUMERIC_CHARACTERS= NLS_DATE_FORMAT=DDMONRR NLS_DATE_LANGUAGE=AMERICAN NLS_SORT=BINARY
xd(=>NULL)
×bfe(=>×)
[ ::]User call: _rpisplu (TID: )
[Args()]:
×(=>NULL)
×(=>NULL)
select sysdate + / ( * ) from dual
×(=>NULL)
[ ::]User call: _rpisplu (TID: )
[Args()]:
×(=>NULL)
×(=>NULL)
DECLARE job BINARY_INTEGER := :job; next_date DATE := :mydate; broken BOOLEAN := FALSE; BEGIN EMD_MAINTENANCEEXECUTE_EM_DBMS_JOB_PROCS(); :mydate := next_date; IF broken THEN :b := ; ELSE :b := ; END IF; END;
xd(=>NULL)
…
點擊Stop按鈕停止追蹤
例子 :
理解SQL是如何被執行計劃驅動執行的
我們知道查詢計劃實際上就是驅動Oracle通過特定函數及順序來獲取數據我們可以通過追蹤這些函數來理解執行計劃
首先下載以下文件解壓重命名為TracePointstxt放到OraTracerexe所在目錄
然後獲取到你需要追蹤的會話的SPID
SQL代碼
HELLODBACOM>select distinct spid from v$mystat m v$session s v$process p where ssid=msid and spaddr=paddr;
SPID
————
從進程列表中選擇ORACLEEXE => 從線程列表中選擇TID為的線程 => 點擊Trace按鈕
在被追蹤的會話中執行一條語句
SQL代碼
HELLODBACOM>select * from demot_test where owner=DEMO and object_name like T_TEST%;
OWNER OBJECT_NAME SUBOBJECT_NAME OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE CREATED
LAST_DDL_TIME TIMESTAMP STATUS T G S
—————————— —————————— —————————— ——— ————– —————— ———–
——– —————— —————— ——
DEMO T_TEST AAA TABLE
:: :: ::: VALID N N N
注意為了避免回滾調用也被追蹤你最好在追蹤之前先運行一次該語句
我們可以從追蹤窗口看到數據fetch調用情況
SQL代碼
[ ::]User call: _qertbFetchByRowID (TID: )
[ ::]User call: _qerixtFetch (TID: )
[ ::]User call: _qertbFetchByRowID (TID: )
[ ::]User call: _qerixtFetch (TID: )
有了這樣的追蹤記錄你可以嘗試將他們與執行計劃中節點映射
SQL代碼
HELLODBACOM>select * from demot_test where owner=DEMO and object_name like T_TEST%;
Execution Plan
———————————————————
Plan hash value:
——————————————————————————————
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
——————————————————————————————
| | SELECT STATEMENT | | | | ()| :: |
| | TABLE ACCESS BY INDEX ROWID| T_TEST | | | ()| :: | ==> _qertbFetchByRowID
|* | INDEX RANGE SCAN | T_TEST_IDX | | | ()| :: | ==> _qerixtFetch
例子 :
打印某個特定函數被調用時的線程調用堆棧
我們這裡追蹤_kkeAdjSingTabCard設置追蹤點
SQL代碼
_kkeAdjSingTabCard*
函數名後的*N指定輸出的調用個數為無限制
然後獲取到你需要追蹤的會話的SPID
SQL代碼
HELLODBACOM>select distinct spid from v$mystat m v$session s v$process p where ssid=msid and spaddr=paddr;
SPID
————
從進程列表中選擇ORACLEEXE => 從線程列表中選擇TID為的線程 => 點擊Trace按鈕
在被追蹤的會話中解釋一條語句
SQL代碼
HELLODBACOM>explain plan for select /*+full(t)*/ count(*) from demot_test t;
Explained
我們就可以從監控窗口獲取到該函數被調用時的整個調用堆棧的情況
SQL代碼
[ ::]User call: _kkeAdjSingTabCard (TID: )
Call Stacks():
× (ORACLEEXE!_kkoitbp+)
×cd (ORACLEEXE!_kkoijbad+)
×db (ORACLEEXE!_kkoCopyPreds+)
×eea (ORACLEEXE!_kkosta+)
×dfc (ORACLEEXE!__PGOSF__apaRequestBindCapture+)
×d (ORACLEEXE!_apagcp+)
×dc (ORACLEEXE!_apafbr+)
xea (ORACLEEXE!_opitcaNcp+)
×beb (ORACLEEXE!_kksMinimalTypeCheck+)
×d (ORACLEEXE!_rpidrus+)
×bce (ORACLEEXE!_kksSetNLSHandle+)
×e (ORACLEEXE!_kxsReleaseRuntimeLock+)
× (ORACLEEXE!_kkscbt+)
×ecf (ORACLEEXE!_kksParseCursor+)
×fb (ORACLEEXE!_kksxsccompat+)
×e (ORACLEEXE!_opibrp+)
×cded (ORACLEEXE!_kpodrd+)
×cbac (ORACLEEXE!_kpocrs+)
×e (ORACLEEXE!_opirip+)
×feff (oracommondll!_ttcpro+)
×a (ORACLEEXE!_opiodr+)
× (ORACLEEXE!_opiino+)
×e (ORACLEEXE!_opirip+)
×e (ORACLEEXE!_opidcl+)
×a (ORACLEEXE!_ksdwri+)
× (ORACLEEXE!_ssthrnfy+)
× (ORACLEEXE!_opimai_init+)
× (ORACLEEXE!_osnsoiint+)
×cb (KERNELdll!GetModuleFileNameA+)
[Args()]:
×ed
×eda
×a
×
From:http://tw.wingwit.com/Article/program/Oracle/201311/18739.html