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 ?

Oracle内部latch获取函数简介的更多相关文章

  1. Delphi 版本信息获取函数 GetFileVersionInfo、GetFileVersionInfoSize、VerFindFile、VerInstallFile和VerQueryValue

    一.版本信息获取函数简介和作用 获取文件版本信息的作用: 1. 避免在新版本的组件上安装旧版本的相同组件: 2. 在多语言系统环境中,操作系统根据文件版本信息里提供的语言信息在启动程序时决定使用的正确 ...

  2. [转帖学习]Oracle的 SYS_CONTEXT 函数简介

    Oracle的 SYS_CONTEXT 函数简介 https://blog.csdn.net/IndexMan/article/details/48606369 1.什么是SYS_CONTEXT? S ...

  3. Linux Shell系列教程之(十五) Shell函数简介

    本文是Linux Shell系列教程的第(十五)篇,更多Linux Shell教程请看:Linux Shell系列教程 函数可以将一个复杂功能划分成若干模块,从而使程序结构更加清晰,代码重复利用率更高 ...

  4. PCRE函数简介和使用示例【转】

    PCRE函数简介和使用示例 标签: 正则表达式listbuffercompilationnullperl 原文地址:http://blog.csdn.net/sulliy/article/detail ...

  5. linux进程编程:子进程创建及执行函数简介

    linux进程编程:子进程创建及执行函数简介 子进程创建及执行函数有三个: (1)fork();(2)exec();(3)system();    下面分别做详细介绍.(1)fork()    函数定 ...

  6. [转]SQLITE3 C语言接口 API 函数简介

    SQLITE3 C语言接口 API 函数简介 说明:本说明文档属作者从接触 SQLite 开始认识的 API 函数的使用方法, 由本人翻译, 不断更新. /* 2012-05-25 */ int sq ...

  7. Oracle中的单行函数

    Oracle中的单行函数 1 字符函数 UPPER()--将字符串转换为大写 SELECT UPPER('abc') FROM dual; LOWER()-将字符串转换为小写 SELECT LOWER ...

  8. 创建类似于Oracle中decode的函数

    -- 创建类似于Oracle中decode的函数create or replace function decode(variadic p_decode_list text[])returns text ...

  9. UNIX网络编程——epoll 系列函数简介、与select、poll 的区别

    前面博客<<UNIX环境高级编程--epoll函数使用详解>>有关于epoll函数的讲解. 一.epoll 系列函数简介 #include <sys/epoll.h> ...

随机推荐

  1. 逻辑与(&)和短路与(&&)的关系

    逻辑与(&)和短路与(&&)在运算上对条件的结果判断不会产生影响,但会对条件判断的运算有影响.关键在于,逻辑与(&)在运算时会连续运算所有需要判断的命令.但短路与当遇到 ...

  2. BZOJ 4244: 邮戳拉力赛

    转化为括号序列DP 注意边界 #include<cstdio> #include<algorithm> #define rep(i,x,y) for (int i=x; i&l ...

  3. HDU 5379 树形DP Mahjong tree

    任意一棵子树上节点的编号连续,每个节点的所有二字节点连续,求编号方案的总数. 稍微分析一下可知 每个节点的非叶子节点个数不能多于两个,否则这个子树无解,从而整棵树都无解. 每棵子树将所有节点按照编号从 ...

  4. java处理excel

    JAVA EXCEL API:是一开放源码项目,通过它Java开发人员可以读取Excel文件的内容.创建新的Excel文件.更新已经存在的Excel文件.使用该API非Windows操作系统也可以通过 ...

  5. luogu2158 [SDOI2008]仪仗队 欧拉函数

    点 $ (i,j) $ 会看不见当有 $ k|i $ 且 $ k|j$ 时. 然后就成了求欧拉函数了. #include <iostream> #include <cstring&g ...

  6. tomcat6-输入输出buffer设计

    之前写的一个ppt 搬到博客来

  7. Uiautomator学习笔记(2) 封装代码 报错误(NllPointerException)

    .NullPointerException: Attempt to invoke virtual method 'boolean qq.test.UiautomatorAssistant.ClickB ...

  8. 九度oj 题目1373:整数中1出现的次数(从1到n整数中1出现的次数)

    题目描述: 亲们!!我们的外国友人YZ这几天总是睡不好,初中奥数里有一个题目一直困扰着他,特此他向JOBDU发来求助信,希望亲们能帮帮他.问题是:求出1~13的整数中1出现的次数,并算出100~130 ...

  9. Welcome-to-Swift-14构造过程(Initialization)

    构造过程是为了使用某个类.结构体或枚举类型的实例而进行的准备过程.这个过程包含了为实例中的每个属性设置初始值和为其执行必要的准备和初始化任务. 构造过程是通过定义构造器(Initializers)来实 ...

  10. R语言处理1975-2011年的人口信息

    1975-2011年的数据中. 1)分别统计每年人口最多的国家是哪个?有多少 2)统计出各个国家的1975-2011年的平均人口增长率 3)统计每年人口最多的十个国家 4)统计出每年人口最少的十个国家 ...