[20210524]分析library cache转储 3.txt

[20210524]分析library cache转储 3.txt

--//前几天探究11g shared pool latch与library cache mutex时,分析11g library cache转储,里面的mutex地址我当时得出的结论是每
--//个占用40字节.实际上犯了一点点错误,仅仅说明下一个mutext地址在偏移40字节的位置.实际上muext仅仅占用24个字节.
--//这个问题的产生在于我当时使用oradebug peek查看的遇到的情况:

SYS@book> oradebug peek 0x80528f40 40
[080528F40, 080528F68) = 00000001 00000000 0000092B 00042180 000190FA 00000006 80528F58 00000000 80528F58 00000000

--//我后面16字节始终不变,而且如果0x080528F40+0x18(十进制24)=0x80528F58,正好等于对应地址.
--//我当时推断0000092B => 表示get,00042180 表示与sleep相关,000190FA = 102650表示bucket,00000006 不知道.

--//我想既然不变,尝试peek地址 0x80528f40-0x10(十进制16)=0x80528f30的情况,当我看到对比dump library cache,马上明白其中的奥秘.
--//当时快下班了,也没心情继续探究,找一个完整的时间仔细探究看看.

1.环境:
SCOTT@book> @ ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx            11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

2.分析:
--//退出全部session。执行:
--//session 2:
SYS@book> alter system flush shared_pool;
System altered.

SYS@book> oradebug setmypid
Statement processed.

SYS@book> oradebug peek 0x80528f30 40
[080528F30, 080528F58) = 80528F30 00000000 80528F30 00000000 00000000 00000000 00000077 00000000 000190FA 00000000
--//0x80528F30 正好等于 peek的开始地址,也就是当bucket里面没有对象时,该地址正好等于开始地址。

--//session 1:
SCOTT@book> select * from dept where deptno=20;
    DEPTNO DNAME          LOC
---------- -------------- -------------
        20 RESEARCH       DALLAS

--//执行多次,避免该光标不在共享池中.

SCOTT@book> @ hash
HASH_VALUE SQL_ID        CHILD_NUMBER HASH_HEX
---------- ------------- ------------ ---------
  95129850 80baj2c2ur47u            0   5ab90fa
--//95129850%131072   = 102650

--//session 2:
SYS@book> oradebug peek 0x80528f30 40
[080528F30, 080528F58) = 7C1B0958 00000000 7C1B0958 00000000 00000000 00000000 0000007B 00000000 000190FA 00000000

--//注意看现在记录的是0x7C1B0958,表示什么呢?

SYS@book> @ sharepool/shp4 80baj2c2ur47u 0

TEXT                  KGLHDADR         KGLHDPAR         C40                                        KGLHDLMD   KGLHDPMD   KGLHDIVC KGLOBHD0         KGLOBHD6           KGLOBHS0   KGLOBHS6   KGLOBT16   N0_6_16        N20   KGLNAHSH KGLOBT03        KGLOBT09
--------------------- ---------------- ---------------- ---------------------------------------- ---------- ---------- ---------- ---------------- ---------------- ---------- ---------- ---------- --------- ---------- ---------- ------------- ----------
child handle address  000000007C57C898 000000007C1B0958 select * from dept where deptno=20                1          0          0 000000007E1C1220 000000007EA4AD40       4536      12144       3067     19747      19747   95129850 80baj2c2ur47u          0
parent handle address 000000007C1B0958 000000007C1B0958 select * from dept where deptno=20                1          0          0 000000007E1A22C0 00                     4720          0          0      4720       4720   95129850 80baj2c2ur47u      65535
--//正好记录的就是是父游标的handle地址。0x000000007C1B0958。

SYS@book> @fcha 000000007C1B0958
Find in which heap (UGA, PGA or Shared Pool) the memory address 000000007C1B0958 resides...

WARNING!!! This script will query X$KSMSP, which will cause heavy shared pool latch contention
in systems under load and with large shared pool. This may even completely hang
your instance until the query has finished! You probably do not want to run this in production!

Press ENTER to continue, CTRL+C to cancel...

LOC KSMCHPTR           KSMCHIDX   KSMCHDUR KSMCHCOM           KSMCHSIZ KSMCHCLS   KSMCHTYP KSMCHPAR
--- ---------------- ---------- ---------- ---------------- ---------- -------- ---------- ----------------
SGA 000000007C1B0928          1          1 KGLHD                   560 recr             80 00
--//父游标句柄地址记录的是000000007C1B0958,与开头偏移0x30(48字节)。
--// 0x000000007C1B0958-0x30=0x000000007C1B0928

SYS@book> oradebug peek 0x000000007C1B0928 560 1
[07C1B0928, 07C1B0B58) = 00000231 80B38F00 7C1B06F8 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 40080050 80528F30 00000000 ...
                                                                                                                                     ~~~~~~~~
--//注意看下划线内容,可以发现正好记录的是bucket 的地址。这样就形成了一个链表。

3.分析转储:

SYS@book> @ tix
New tracefile_identifier =  /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_40996_0001.trc

SYS@book> oradebug dump library_cache 10;
Statement processed.

--//检索Bucket: #=102650.

Bucket: #=102650 Mutex=0x80528f40(0, 127, 0, 6)
  LibraryHandle:  Address=0x7c1b0958 Hash=5ab90fa LockMode=N PinMode=0 LoadLockMode=0 Status=VALD
--//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=>父游标句柄。
    ObjectName:  Name=select * from dept where deptno=20
      FullHashValue=e8ec445edab00042802d511305ab90fa Namespace=SQL AREA(00) Type=CURSOR(00) Identifier=95129850 OwnerIdn=83
    Statistics:  InvalidationCount=0 ExecutionCount=5 LoadCount=2 ActiveLocks=1 TotalLockCount=3 TotalPinCount=1
    Counters:  BrokenCount=1 RevocablePointer=1 KeepDependency=1 Version=0 BucketInUse=2 HandleInUse=2 HandleReferenceCount=0
    Concurrency:  DependencyMutex=0x7c1b0a08(0, 1, 0, 0) Mutex=0x7c1b0a98(44, 35, 0, 6)
    Flags=RON/PIN/TIM/PN0/DBN/[10012841]
    WaitersLists:
      Lock=0x7c1b09e8[0x7c1b09e8,0x7c1b09e8]
      Pin=0x7c1b09c8[0x7c1b09c8,0x7c1b09c8]
      LoadLock=0x7c1b0a40[0x7c1b0a40,0x7c1b0a40]
    Timestamp:  Current=05-24-2021 08:28:01
    HandleReference:  Address=0x7c1b0b28 Handle=(nil) Flags=[00]
    ReferenceList:
      Reference:  Address=0x7cae8b10 Handle=0x7caea870 Flags=ROD[21]
    LibraryObject:  Address=0x7ea4a680 HeapMask=0000-0001-0001-0000 Flags=EXS[0000] Flags2=[0000] PublicFlags=[0000]
      DataBlocks:
        Block:  #='0' name=KGLH0^5ab90fa pins=0 Change=NONE
          Heap=0x7e1a22c0 Pointer=0x7ea4a720 Extent=0x7ea4a600 Flags=I/-/P/A/-/-
          FreedLocation=0 Alloc=2.437500 Size=3.976562 LoadTime=13159699060
      ChildTable:  size='16'
        Child:  id='0' Table=0x7ea4b530 Reference=0x7ea4af70 Handle=0x7c57c898
    NamespaceDump:
      Parent Cursor:  sql_id=80baj2c2ur47u parent=0x7ea4a720 maxchild=1 plk=y ppn=n

--//现在就很清晰了,muext结构体仅仅占用24字节,bucket+muext的结构大致如下:
--//bucket 占用16字节 +muext 占用24字节。
--//bucket 应该保存地址,我猜测一个链表的开始地址,一个是结束地址。至于那个在前那个在后我现在还不能确定。
--//如果多个对象在一个bucket里面通过通过父游标或者对应对象里面里面记录下一个对象的句柄来实现链接的,这样就能实现检索功能。
--//可以通过找一些hash_value一样的sql语句来验证自己的判断。

--//退出session 1:
--//session 2:
SYS@book> alter system flush shared_pool;
System altered.

SYS@book> oradebug peek 0x80528f30 40
[080528F30, 080528F58) = 80528F30 00000000 80528F30 00000000 00000000 00000000 00000083 00000000 000190FA 00000000
--//回到没有对象的情况。

4.附上执行脚本:
$ cat sharepool/shp4.sql
column N0_6_16 format 99999999
SELECT DECODE (kglhdadr,
               kglhdpar, 'parent handle address',
               'child handle address')
          text,
       kglhdadr,
       kglhdpar,
       substr(kglnaobj,1,40) c40,
           KGLHDLMD,
           KGLHDPMD,
           kglhdivc,
       kglobhd0,
       kglobhd6,
       kglobhs0,kglobhs6,kglobt16,
       kglobhs0+kglobhs6+kglobt16 N0_6_16,
           kglobhs0+kglobhs1+kglobhs2+kglobhs3+kglobhs4+kglobhs5+kglobhs6+kglobt16 N20,
           kglnahsh,
           kglobt03 ,
           kglobt09
  FROM x$kglob
 WHERE kglobt03 = '&1'  or kglhdpar='&1' or kglhdadr='&1' or KGLNAHSH= &2;

$ cat tpt/fcha.sql
--------------------------------------------------------------------------------
--
-- File name:   fcha.sql (Find CHunk Address) v0.2
-- Purpose:     Find in which heap (UGA, PGA or Shared Pool) a memory address resides
--
-- Author:      Tanel Poder
-- Copyright:   (c) http://blog.tanelpoder.com | @tanelpoder
--
-- Usage:       @fcha <addr_hex>
--              @fcha F6A14448
--
-- Other:       This would only report an UGA/PGA chunk address if it belongs
--              to *your* process/session (x$ksmup and x$ksmpp do not see other
--              session/process memory)
--
--------------------------------------------------------------------------------

prompt Find in which heap (UGA, PGA or Shared Pool) the memory address &1 resides...
prompt
prompt WARNING!!! This script will query X$KSMSP, which will cause heavy shared pool latch contention
prompt in systems under load and with large shared pool. This may even completely hang
prompt your instance until the query has finished! You probably do not want to run this in production!
prompt
pause  Press ENTER to continue, CTRL+C to cancel...


select
    'SGA' LOC,
    KSMCHPTR,
    KSMCHIDX,
    KSMCHDUR,
    KSMCHCOM,
    KSMCHSIZ,
    KSMCHCLS,
    KSMCHTYP,
    KSMCHPAR
from
    x$ksmsp
where
    to_number(substr('&1', instr(lower('&1'), 'x')+1) ,'XXXXXXXXXXXXXXXX')
    between
        to_number(ksmchptr,'XXXXXXXXXXXXXXXX')
    and to_number(ksmchptr,'XXXXXXXXXXXXXXXX') + ksmchsiz - 1
union all
select
    'UGA',
    KSMCHPTR,
    null,
    null,
    KSMCHCOM,
    KSMCHSIZ,
    KSMCHCLS,
    KSMCHTYP,
    KSMCHPAR
from
    x$ksmup
where
    to_number(substr('&1', instr(lower('&1'), 'x')+1) ,'XXXXXXXXXXXXXXXX')
    between
        to_number(ksmchptr,'XXXXXXXXXXXXXXXX')
    and to_number(ksmchptr,'XXXXXXXXXXXXXXXX') + ksmchsiz - 1
union all
select
    'PGA',
    KSMCHPTR,
    null,
    null,
    KSMCHCOM,
    KSMCHSIZ,
    KSMCHCLS,
    KSMCHTYP,
    KSMCHPAR
from
    x$ksmpp
where
    to_number(substr('&1', instr(lower('&1'), 'x')+1) ,'XXXXXXXXXXXXXXXX')
    between
        to_number(ksmchptr,'XXXXXXXXXXXXXXXX')
    and to_number(ksmchptr,'XXXXXXXXXXXXXXXX') + ksmchsiz - 1
/




posted @ 2021-05-24 08:54  lfree  阅读(90)  评论(0编辑  收藏  举报