标签: oracle call 函数 oracle statpack
转自: http://blog.51cto.com/458302/998775
Oracle的内部函数一直非常神秘,其实Oracle提供了一个oradebug 工具,可以用于调用内部的一些方法/函数,这为我们窥探Oracle的内部机制打开了一扇窗户。
比如:Oracle内部获取latch的函数为kslgetl,全称为Kernel Service Lock Management Get Latch,可以使用oradebug call kslgetl/kslfre命令来手动获取一个latch,这种方法可用于模拟latch争用相关的现象。
kslgetl函数有四个参数,调用格式如下:
kslgetl(laddr, wait, why, where)
参数说明如下:
laddress – latch在 SGA中的地址
wait – flag. 如果设置为true,表示使用 willing-to-wait mode模式。
where – 请求latch的代码段位置 ,也就是awr/statpack的Latch Misses Source中的内容。
why - 为什么从Where参数指定的地方请求latch
注意where中的位置值只是一个索引,具体的位置名称从v$latch_misses可以查到(或者从awr/statspack也可以看到)。代码位置的名称和索引存储在视图x$ksllw
SQL> select indx, ksllwnam,ksllwlbl from x$ksllw where rownum<20;
INDX KSLLWNAM KSLLWLBL
---------- ---------------------------------------------------------------- ----------------------------------------------------------------
0 No latch
1 kslwt
2 ksudlp
3 kslpstevent:get pwq#
4 kslpstevent:reget pwq#
5 ksliwat:add:nowait pwq#
6 ksliwat:remove pwq#
7 ksliwat:add:wait pwq#
8 kslael
9 kslrgpl_parent
10 kslrgpl_2child
INDX KSLLWNAM KSLLWLBL
---------- ---------------------------------------------------------------- ----------------------------------------------------------------
11 kslrgpl_notsib
12 kslrgp_nowait
13 ksqgel: create enqueue parent obj
14 ksqgel: failed to get enqueue error
视图v$latch_misses的基础表是x$kslwsc,在这个表里Oracle维护了一个latch丢失代码位置的数组。x$kslwsc(猜测的名称为:kernel service where of source code),通过这个视图,可以找到latch对应的索引:
SQL> desc x$kslwsc;
Name Null? Type ----------------------------------------------------------------------------- -------- ---------------------------------------------------- ADDR RAW(8) INDX NUMBER INST_ID NUMBER KSLNOWTF NUMBER KSLSLEEP NUMBER KSLWSCWSL NUMBER KSLWSCLTHG NUMBER
KSLLASNAM VARCHAR2(50)
why参数的在dump出来的结果中描述是“Context saved from call”,例如:
SO: 0x2d93be720, type: 2, owner: (nil), flag: INIT/-/-/0x00 (process) Oracle pid=299, calls cur/top: 0x2e9028a38/0x2e9028a38, flag: (0)… (latch info) wait_event=0 bits=2 holding 2dee1ac50 Child cache buffers chains level=1 child#=124200 Location from where latch is held: kcbgtcr: fast path: Context saved from call: 39022946
why参数说明为什么在这个(where)请求这个latch,它依赖于latch的作用与latch请求的where。比如,当请求一个cache buffer chain latch保护的一个数据块时,why就包括一个块地址(dba)。why的意义,可以从x$ksllw中的ksllwlbl列进行一些猜测。
where与why参数用于获取一个latch,当latch获取成功后,Oracle保存参数的值到latch的结构中.Oracle 11g更进一步扩展了latch架构,存储在x$kslltr_parent和x$kslltr_children视图中,分别表示parent latch与children latch。10g或以前的版本,都是使用x$ksllt表,v$latch与v$latch_children都是以x$ksllt为基表。 最近获取latch的"Where"与"Why"的值可以从这些表的kslltwhr与kslltwhy两个表查询到。
x$ksuprlat显示持有latch的进程,他是v$latchholder的基表,where与why的值也在它的ksulawhr与ksulawhy列中。
我们来手动获取一个latch试试看:
SQL> select addr, name from v$latch where name like 'shared pool';
ADDR NAME
---------------- --------------------------------------------------
0000000380019DA8 shared pool
SQL>
取这个latch的where值,也就是代码位置:
SQL> select * from x$kslwsc where ksllasnam ='shared pool';
ADDR INDX INST_ID KSLNOWTF KSLSLEEP KSLWSCWSL KSLWSCLTHG KSLLASNAM
---------------- ---------- ---------- ---------- ---------- ---------- ---------- ------------
............
00000005F7152178 2582 1 0 0 0 0 shared pool
00000005F7152198 2583 1 0 0 0 0 shared pool
00000005F71521B8 2584 1 0 0 0 0 shared pool
00000005F71521D8 2585 1 0 0 0 0 shared pool
62 rows selected
这些值也可以从x$ksllt取到
SQL> select kslltwhr,kslltwhy from x$ksllt where addr='0000000380019DA8';
KSLLTWHR KSLLTWHY
---------- ----------
2559 208
SQL>
现在我们用oradebug手动执行kslgetl函数:
SQL> connect /as sysdba;
Connected.
SQL> oradebug setmypid;
Statement processed.
SQL> oradebug call kslgetl 0 x380019DA8 1 208 2559
ORA-03113: end-of-file on communication channel
ORA-24323: value not allowed
发现出错了,查看trace文件,可以看到出现了一个ora-007445 [Address not mapped to object]错误:
*** 2012-03-10 15:00:56.229
ksedmp: internal or fatal error
ORA-07445: exception encountered: core dump [kslgetl()+8] [SIGSEGV] [Address not mapped to object] [0xFFFFFFFF80021E44] [] []
----- Call Stack Trace -----
calling call entry argument values in hex
location type point (? means dubious value)
-------------------- -------- -------------------- ----------------------------
ksedmp()+728 CALL ksedst() 000000017 ? 106B520AC ?
000000000 ? 106B4EBA0 ?
106B4D908 ? 106B4E308 ?
ssexhd()+1232 CALL ksedmp() 106994000 ? 10699493C ?
000106800 ? 10699493C ?
000000000 ? 106994000 ?
__sighndlr()+12 PTR_CALL 0000000000000000 106991000 ? 106B55EF0 ?
10698E81C ? 000106991 ?
00000000B ? 000000067 ?
call_user_handler() CALL __sighndlr() 00000000B ? 106B55EF0 ?
+992 106B55C10 ? 102084BC0 ?
000000000 ? 00000000A ?
sigacthandler()+104 CALL call_user_handler() FFFFFFFF7D100200 ?
FFFFFFFF7D100200 ?
106B55C10 ? 000000009 ?
000000000 ? 000000000 ?
kslgetl()+8 PTR_CALL 0000000000000000 000000000 ? 106B55EF0 ?
106B55C10 ?
FFFFFFFF7D100200 ?
000000000 ?
FFFFFFFF7C33E000 ?
skdxcall()+1664 PTR_CALL 0000000000000000 FFFFFFFF80021E38 ?
000000001 ? 0000000D0 ?
0000009FF ?
FFFFFFFF7FFFABC0 ?
0000009FF ?
ksdxen()+3672 PTR_CALL 0000000000000000 380021E38 ?
FFFFFFFF7FFFB350 ?
FFFFFFFF7FFFB348 ?
FFFFFFFF7FFFB340 ?
FFFFFFFF7FFFB3F0 ?
FFFFFFFF7FFFB338 ?
opiodr()+1536 PTR_CALL 0000000000000000 105AB8000 ? 1020766C0 ?
10699294A ? 000105800 ?
000106800 ? 106991CA8 ?
ttcpip()+1188 PTR_CALL 0000000000000000 105AE96F0 ? 105E47870 ?
000106991 ? 106991000 ?
000000056 ? 000106800 ?
opitsk()+1532 CALL ttcpip() 00000001E ? 000000000 ?
FFFFFFFF7FFFE5B8 ?
000000001 ?
FFFFFFFF7FFFD090 ?
10698F208 ?
opiino()+1128 CALL opitsk() 000000000 ? 105E46B00 ?
000000000 ? 000100000 ?
105A9E49C ? 10699D160 ?
opiodr()+1536 PTR_CALL 0000000000000000 00010699B ? 000000000 ?
相关阅读
发表评论