登录  /  注册
Oracle内部函数调用追踪器详解
php中文网
发布: 2016-06-07 15:45:09
原创
1160人浏览过

基于以前开发的一个用于监控线程的CPU使用状况的小工具,TopShow,我开发了一个用于追踪Oracle内部函数调用的追踪器——OraTracer. 你可以用该工具追踪监控Oracle多个内部函数的调用情况,还可以尝试探测函数的输入参数的,也可以打印追踪点被触发时的调用堆

基于以前开发的一个用于监控线程的CPU使用状况的小工具,TopShow,我开发了一个用于追踪Oracle内部函数调用的追踪器——OraTracer. 你可以用该工具追踪监控Oracle多个内部函数的调用情况,还可以尝试探测函数的输入参数的值,也可以打印追踪点被触发时的调用堆栈。追踪可以设置在整个Oracle进程的级别,也可以设置在某个线程以追踪特定的会话。

  例子 1:

  捕获oracle整个实例中被执行的SQL语句。

  首先,在与可执行文件相同的目录下设置追踪点文件”TracePoints.txt”,内容如下:

  _opiprs 6*1

  _rpisplu 6*2

  _kprbprs 6

  与函数名用空格相隔的数值为探测的参数数量,如果再加上”*N”,则表示尝试将双字节数字作为指针对待,递归获取其执行的值,后面的数字为递归深度。例如,对于第一个追踪点,函数名为”_opiprs”,探测6个参数,递归探测指针数据的深度为1。

  注意:”#”为注释符。

  然后从进程列表中选择”ORACLE.EXE”,不要选择任何线程:

Oracle内部函数调用追踪器详解

  最后,点击”Trace”按钮。一旦有语句被上述函数调用,你就可以从监控窗口看到这些语句:

  SQL代码

  …

  [2010-5-28 3:53:23.426]User call: _rpisplu (TID: 5276)

  [Args(6)]:

  6

  0

  0

  “select privilege#,level from sysauth$ connect by grantee#=prior privilege# and privilege#>0 start with grantee#=:1 and privilege#>0“

  0×84(=>NULL)

  0

  [2010-5-28 3:53:23.442]User call: _rpisplu (TID: 5276)

  [Args(6)]:

  6

  0

  0

  “alter session set NLS_LANGUAGE=’AMERICAN’ NLS_TERRITORY=’AMERICA’ NLS_CURRENCY=’$’ NLS_ISO_CURRENCY=’AMERICA’ NLS_NUMERIC_CHARACTERS=’.,’ NLS_DATE_FORMAT=’DD-MON-RR’ NLS_DATE_LANGUAGE=’AMERICAN’ NLS_SORT=’BINARY’“

  0xd4(=>NULL)

  0

  [2010-5-28 3:53:23.473]User call: _opiprs (TID: 5276)

  [Args(6)]:

  0×70cce00(=>0×4000000)

  “alter session set NLS_LANGUAGE=’AMERICAN’ NLS_TERRITORY=’AMERICA’ NLS_CURRENCY=’$’ NLS_ISO_CURRENCY=’AMERICA’ NLS_NUMERIC_CHARACTERS=’.,’ NLS_DATE_FORMAT=’DD-MON-RR’ NLS_DATE_LANGUAGE=’AMERICAN’ NLS_SORT=’BINARY’“

  0xd5(=>NULL)

  0×4bfe214(=>0×18)

  0

  6

  [2010-5-28 3:53:23.504]User call: _rpisplu (TID: 5276)

  [Args(6)]:

  3

  0×20(=>NULL)

  0×20(=>NULL)

  “select sysdate + 1 / (24 * 60) from dual“

  0×28(=>NULL)

  1

  [2010-5-28 3:53:23.520]User call: _rpisplu (TID: 5276)

  [Args(6)]:

  5

  0×20(=>NULL)

  0×20(=>NULL)

  “DECLARE job BINARY_INTEGER := :job; next_date DATE := :mydate; broken BOOLEAN := FALSE; BEGIN EMD_MAINTENANCE.EXECUTE_EM_DBMS_JOB_PROCS(); :mydate := next_date; IF broken THEN :b := 1; ELSE :b := 0; END IF; END; “

  0xd5(=>NULL)

  0

  …

  点击”Stop”按钮,停止追踪。

  例子 2:

  理解SQL是如何被执行计划驱动执行的。

  我们知道,查询计划实际上就是驱动Oracle通过特定函数及顺序来获取数据。我们可以通过追踪这些函数来理解执行计划。

  首先下载以下文件,解压,重命名为”TracePoints.txt”,放到OraTracer.exe所在目录:

  http://www.HelloDBA.com/download/TracePoints_ALL_Query_Calls.zip

  然后获取到你需要追踪的会话的SPID:

  SQL代码

  HELLODBA.COM>select distinct spid from v$mystat m, v$session s, v$process p where s.sid=m.sid and s.paddr=p.addr;

  SPID

  ————

  11076

  从进程列表中选择ORACLE.EXE => 从线程列表中选择TID为11076的线程 => 点击”Trace”按钮

  在被追踪的会话中执行一条语句:

  SQL代码

  HELLODBA.COM>select * from demo.t_test1 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_TEST1 AAA 97819 97819 TABLE 2007-06-07

  13:48:08 2007-06-07 13:48:08 2007-06-07:13:48:08 VALID N N N

  注意:为了避免回滚调用也被追踪,你最好在追踪之前先运行一次该语句。

  我们可以从追踪窗口看到数据fetch调用情况:

  SQL代码

  [2010-5-28 6:28:29.649]User call: _qertbFetchByRowID (TID: 11076)

  [2010-5-28 6:28:29.711]User call: _qerixtFetch (TID: 11076)

  [2010-5-28 6:28:29.727]User call: _qertbFetchByRowID (TID: 11076)

  [2010-5-28 6:28:29.727]User call: _qerixtFetch (TID: 11076)

有了这样的追踪记录,你可以尝试将他们与执行计划中节点映射:

  SQL代码

  HELLODBA.COM>select * from demo.t_test1 where owner=‘DEMO’ and object_name like ‘T_TEST%’;

  Execution Plan

  ———————————————————-

  Plan hash value: 698582444

  ——————————————————————————————-

  | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

  ——————————————————————————————-

  | 0 | SELECT STATEMENT | | 5 | 495 | 4 (0)| 00:00:04 |

  | 1 | TABLE ACCESS BY INDEX ROWID| T_TEST1 | 5 | 495 | 4 (0)| 00:00:04 | ==> _qertbFetchByRowID

  |* 2 | INDEX RANGE SCAN | T_TEST_IDX7 | 5 | | 1 (0)| 00:00:02 | ==> _qerixtFetch

  例子 3:

  打印某个特定函数被调用时的线程调用堆栈。

  我们这里追踪”_kkeAdjSingTabCard”。设置追踪点:

  SQL代码

  _kkeAdjSingTabCard*-1 6

  函数名后的”*N”指定输出的调用个数,-1为无限制。

  然后获取到你需要追踪的会话的SPID:

  SQL代码

  HELLODBA.COM>select distinct spid from v$mystat m, v$session s, v$process p where s.sid=m.sid and s.paddr=p.addr;

  SPID

  ————

  11076

  从进程列表中选择ORACLE.EXE => 从线程列表中选择TID为11076的线程 => 点击”Trace”按钮

  在被追踪的会话中解释一条语句:

  SQL代码

  HELLODBA.COM>explain plan for select /*+full(t)*/ count(*) from demo.t_test2 t;

  Explained.

  我们就可以从监控窗口获取到该函数被调用时的整个调用堆栈的情况:

  SQL代码

  [2010-5-28 6:51:55.591]User call: _kkeAdjSingTabCard (TID: 11076)

  Call Stacks(-1):

  0×1460029 (ORACLE.EXE!_kkoitbp+757)

  0×144c44d (ORACLE.EXE!_kkoijbad+8869)

  0×1445d8b (ORACLE.EXE!_kkoCopyPreds+851)

  0×143ee0a (ORACLE.EXE!_kkosta+1694)

  0×1d17f6c (ORACLE.EXE!__PGOSF443__apaRequestBindCapture+156)

  0×1d18398 (ORACLE.EXE!_apagcp+388)

  0×1d1683c (ORACLE.EXE!_apafbr+464)

  0xea6682 (ORACLE.EXE!_opitcaNcp+1450)

  0×5b4eb0 (ORACLE.EXE!_kksMinimalTypeCheck+20)

  0×84d939 (ORACLE.EXE!_rpidrus+429)

  0×5b8ce8 (ORACLE.EXE!_kksSetNLSHandle+5888)

  0×87732e (ORACLE.EXE!_kxsReleaseRuntimeLock+1366)

  0×831815 (ORACLE.EXE!_kkscbt+7237)

  0×82e3cf (ORACLE.EXE!_kksParseCursor+2099)

  0×82f1b8 (ORACLE.EXE!_kksxsccompat+148)

  0×201683e (ORACLE.EXE!_opibrp+1970)

  0×13cd5ed (ORACLE.EXE!_kpodrd+237)

  0×13cba7c (ORACLE.EXE!_kpocrs+780)

  0×85174e (ORACLE.EXE!_opirip+1102)

  0×60feff90 (oracommon10.dll!_ttcpro+1276)

  0×850a69 (ORACLE.EXE!_opiodr+1017)

  0×1221350 (ORACLE.EXE!_opiino3+1092)

  0×85174e (ORACLE.EXE!_opirip+1102)

  0×420e58 (ORACLE.EXE!_opidcl+824)

  0×42164a (ORACLE.EXE!_ksdwri+50)

  0×401171 (ORACLE.EXE!_ssthrnfy+117)

  0×401061 (ORACLE.EXE!_opimai_init+97)

  0×401905 (ORACLE.EXE!_osnsoiint+713)

  0×7c80b729 (KERNEL32.dll!GetModuleFileNameA+442)

  [Args(6)]:

  0×81e58d0

  0×81e5da8

  0

  0×40a03000

  0×8559500

  0

来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 技术文章
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2023 //m.sbmmt.com/ All Rights Reserved | 苏州跃动光标网络科技有限公司 | 苏ICP备2020058653号-1

 | 本站CDN由 数掘科技 提供

登录PHP中文网,和优秀的人一起学习!
全站2000+教程免费学