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. poj 3176 三角数和最大问题 dp算法

    题意:给一个三角形形状的数字,从上到下,要求数字和最大 思路 :dp dp[i+1][j]=max(dp[i+1][j],dp[i][j]+score[i+1][j]) dp[i+1][j+1]=ma ...

  2. Centos7 开机显示 ERST: Failed to get Error Log Address Range” 导致无法开机解决方法

    开机显示 ERST: Failed to get Error Log Address Range”   导致无法开机,也无法重新安装系统,解决方法:开机进入BIOS , 关闭ACPI选项即可正常开机

  3. POJ1719二分匹配

    第一次发文,就是一些学习的心得而已,自己忘得时候就可以来看看,好了废话不多说,直接说说这题的思路. 题意大概是每列只能射中一个白格子,每行可以射多个,让你输出这样的序列,明显的二分图求匹配,用列去选行 ...

  4. 剑指offer算法编程题目部分汇总(解法略)

    总结一下本书中遇到的大部分面试题.面试题3:二维数组中的查找 题目:在一个二维数组中,每一行都按照从左到右的递增顺序排列,每一列都按照从上到下递增的顺序排列,请完成一个函数,输入这样的一个整数,判断数 ...

  5. 01_Java 软、弱引用语法介绍

    文章导读: 从JDK1.2版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期.这四种级别由高到低依次为:强引用.软引用.弱引用和虚引用, 本章内容介绍了Reference的概 ...

  6. Leetcode21--->Merge Two Sorted Lists(合并两个排序的单链表)

    题目: 给出两个排序的单链表,合并两个单链表,返回合并后的结果: 解题思路: 解法还是很简单的,但是需要注意以下几点: 1.  如果两个链表都空,则返回null; 2.  如果链表1空,则返回链表2的 ...

  7. TOJ3031: Multiple bfs

    3031: Multiple Time Limit(Common/Java):2000MS/6000MS     Memory Limit:65536KByte Total Submit: 60   ...

  8. 常用类--Date日期类,SimpleDateFormat日期格式类,Calendar日历类,Math数学工具类,Random随机数类

    Date日期类 Date表示特定的时间,精确到毫秒; 构造方法: public Data() public Date(long date) 常用方法: public long getTime() pu ...

  9. spring AOP详解三

    CGLib采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用方法拦截的结束拦截所有父类方法的调用,并顺势织入横切逻辑.我们采用CGLib技术可以编写一个可以为任何类创建织入横切逻辑代理对象 ...

  10. Linux定时任务Crontab命令详解 转

      linux 系统则是由 cron (crond) 这个系统服务来控制的.Linux 系统上面原本就有非常多的计划性工作,因此这个系统服务是默认启动的.另 外, 由于使用者自己也可以设置计划任务,所 ...