Oracle内部函数调用追踪器

Oracle内部函数调用追踪器,第1张

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

例子

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

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

_opiprs *

_rpisplu *

_kprbprs

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

注意 # 为注释符

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

最后 点击 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= DD MON RR 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= DD MON RR 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 := :jobnext_date DATE := :mydate  broken BOOLEAN := FALSEBEGIN EMD_MAINTENANCE EXECUTE_EM_DBMS_JOB_PROCS():mydate := next_dateIF broken THEN :b := ELSE :b := END IFEND

xd (=>NULL)

点击 Stop 按钮 停止追踪

例子 :

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

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

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

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

SQL代码

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

SPID

————

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

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

SQL代码

HELLODBA >select * from demo t_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代码

HELLODBA >select * from demo t_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代码

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

SPID

————

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

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

SQL代码

HELLODBA >explain plan for select /*+full(t)*/ count(*) from demo t_test t

Explained

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

SQL代码

[ : : ]User call: _kkeAdjSingTabCard (TID: )

Call Stacks( ):

× (ORACLE EXE!_kkoitbp+ )

× c d (ORACLE EXE!_kkoijbad+ )

× d b (ORACLE EXE!_kkoCopyPreds+ )

× ee a (ORACLE EXE!_kkosta+ )

× d f c (ORACLE EXE!__PGOSF __apaRequestBindCapture+ )

× d (ORACLE EXE!_apagcp+ )

× d c (ORACLE EXE!_apafbr+ )

xea (ORACLE EXE!_opitcaNcp+ )

× b eb (ORACLE EXE!_kksMinimalTypeCheck+ )

× d (ORACLE EXE!_rpidrus+ )

× b ce (ORACLE EXE!_kksSetNLSHandle+ )

× e (ORACLE EXE!_kxsReleaseRuntimeLock+ )

× (ORACLE EXE!_kkscbt+ )

× e cf (ORACLE EXE!_kksParseCursor+ )

× f b (ORACLE EXE!_kksxscpat+ )

× e (ORACLE EXE!_opibrp+ )

× cd ed (ORACLE EXE!_kpodrd+ )

× cba c (ORACLE EXE!_kpocrs+ )

× e (ORACLE EXE!_opirip+ )

× feff (oramon dll!_ttcpro+ )

× a (ORACLE EXE!_opiodr+ )

× (ORACLE EXE!_opiino + )

× e (ORACLE EXE!_opirip+ )

× e (ORACLE EXE!_opidcl+ )

× a (ORACLE EXE!_ksdwri+ )

× (ORACLE EXE!_ssthrnfy+ )

× (ORACLE EXE!_opimai_init+ )

× (ORACLE EXE!_osnsoiint+ )

× c b (KERNEL dll!GetModuleFileNameA+ )

[Args( )]:

× e d

× e da

× a

×

lishixinzhi/Article/program/Oracle/201311/18739

用toad 的工具可以进行跟敬念踪。查找toad的路径 右键羡稿液属性 查找相应文件夹 然后 找寻同级目录下的 sql_monitor 这个工具就可以对 Oracle运行数据兄物进行跟踪。

一.在系统级别上设置sql跟踪

该方法优点:可以跟踪所有的oracle的后台进程所执竖颤友行的sql,包括系统后台进程和用户进程,并且可以跟踪所有的 *** 作

缺点:跟踪所有的后台进程,跟踪信息量比较大

1.在sqlplus中以sys/ as sysdba身份登陆到数据库。

2.打开跟踪,在sqlplus中输入alter sysetem set events '10046 trace name context forever,level &level'

(其中&level可以输入1,4,8,12三个级别,不同的级别含有不同级别的信息)

3.然后到ArcMap或ArcCatalog中进行你想跟踪的 *** 作

4.关闭跟踪,在sqlplus中输入alter systemm set events '10046 trace name context off'

5.查找你所跟踪的session的ID

A 修改时间格式:alter session set nls_date_format='YYYY-MM-DD HH24:MI:SS'

B.对使用sde服务的输入:select sid,logon_time from v$session where username=&username and program='gsrvr.exe'

C.对直连这种方式输入:select sid,logon_time from v$session where username=&username and program='ArcCatalog'

select sid,logon_time from v$session where username=&username and program='ArcMap'

(其中&username是程序登陆到数据库的用户名,如果返回多个余槐结果,在根据登陆的时间确定具体的sid值)

6.执行以下的sql语句

SELECTd.VALUE

|| '/'

|| LOWER (RTRIM (i.INSTANCE, CHR (0)))

|| '_ora_'

|| p.spid

|| '.trc' trace_file_name

FROM (SELECT p.spid

FROM v$mystat m, v$session s, v$process p

WHERE m.statistic# = 1 AND s.SID = &SID AND p.addr = s.paddr) p,

(SELECT t.INSTANCE

FROM v$thread t, v$parameter v

WHERE v.NAME = 'thread'

AND (v.VALUE = 0 OR t.thread# = TO_NUMBER (v.VALUE))) i,

(SELECT VALUE

FROM v$parameter

WHERE NAME = 'user_dump_dest') d

在输入sid后,即得到后台的跟踪文件。

二. 在session级别上设置跟踪

该方法只适用于跟踪洞唤登陆数据后所进行的一系列的 *** 作,比如跟踪在ArcCatalog中创建一个Dataset,FeatureClass等的 *** 作

1.在sqlplus中以sys / as sysdba身份登陆到数据库

2.查找你所要跟踪的session的sid和serial#

A 修改时间格式:alter session set nls_date_format='YYYY-MM-DD HH24:MI:SS'

B.对使用sde服务的输入:select sid,serial#,logon_time from v$session where username=&username and program='gsrvr.exe'

C.对直连这种方式输入:select sid,serial#,logon_time from v$session where username=&username and program='ArcCatalog'

select sid,serial#,logon_time from v$session where username=&username and program='ArcMap'

(其中&username是程序登陆到数据库的用户名,如果返回多个结果,在根据登陆的时间确定具体的sid和serial#的值)

3.开始跟踪,输入exec dbms_support.start_trace_in_session(&sid,&serial#,true,true).(如果系统没有安装dbms_support包,可以执行$ORACLE_HOME\rdbms\admin\dbmssupp.sql进行安装)

4.然后到ArcMap或ArcCatalog中进行你想跟踪的 *** 作

5.结束跟踪exec dbms_support.stop_trace_in_session(&sid,&serial#)

6.执行以下的sql语句

SELECTd.VALUE

|| '/'

|| LOWER (RTRIM (i.INSTANCE, CHR (0)))

|| '_ora_'

|| p.spid

|| '.trc' trace_file_name

FROM (SELECT p.spid

FROM v$mystat m, v$session s, v$process p

WHERE m.statistic# = 1 AND s.SID = &SID AND p.addr = s.paddr) p,

(SELECT t.INSTANCE

FROM v$thread t, v$parameter v

WHERE v.NAME = 'thread'

AND (v.VALUE = 0 OR t.thread# = TO_NUMBER (v.VALUE))) i,

(SELECT VALUE

FROM v$parameter

WHERE NAME = 'user_dump_dest') d

在输入sid后,即得到后台的跟踪文件。

三. 在Aix系统下跟踪消耗内存的session的办法

1.在Aix系统上执行export TERM=vt100

2.执行topas命令,确定最占cpu资源的process的进程号

3,然后利用select a.sid,b.serial# from v$session a,v$process b where a.paddr=b.addr and b.spid=&spid

4.确定sid和serial#后利用二方法进行跟踪。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/12120692.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存