zoukankan      html  css  js  c++  java
  • Oracle内部latch获取函数简介

     

     

      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 ?
  • 相关阅读:
    CentOS重置Mysql密码
    2017年2月21日20:35:46
    UEFI+GPT安装windows
    CentOS 7.0 使用 yum 安装 MariaDB 与 MariaDB 的简单配置
    CentOS利用nginx和php-fpm搭建owncloud私有云
    Docker安装CentOS
    CoreOS和Docker入门
    Docker命令学习
    CentOS安装Redis详细教程
    Redis的三种启动方式
  • 原文地址:https://www.cnblogs.com/zengkefu/p/6665644.html
Copyright © 2011-2022 走看看