[20250201]21c library cache mutex的深入探究4.txt

[20250201]21c library cache mutex的深入探究4.txt

--//前面的测试已经大致确定这48字节的具体内容:

--//0-7,8-15字节分别是对象句柄的尾首指针,如果仅仅存在1个对象,两者相等(保存为父游标句柄地址)。如果存在多个对象会形成1
--//个双向链表,如果仅仅存在0个对象,两者等于mutex的地址-0x10。

--//16-23字节是muext的值。
--//24-27字节是mutex gets的数量。
--//28-31字节是mutex sleeps的数量。
--//32-35字节是Bucket桶号,这里是0,比较不明显。
--//36-39字节是转储看到的6,这是我猜的的,如果你修改其他值,dump看到还是6。

--//40-47字节似乎是某个地址,以前11g没有这部分内容,本文在一些细节上在验证看看。

1.环境:
SCOTT@book01p> @ ver2
==============================
PORT_STRING                   : x86_64/Linux 2.4.xx
VERSION                       : 21.0.0.0.0
BANNER                        : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
BANNER_FULL                   : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
BANNER_LEGACY                 : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
CON_ID                        : 0
PL/SQL procedure successfully completed.

2.测试:
--//先确定某条sql语句的KGL_BUCKET。
SCOTT@book01p> select * from dept where deptno= 20;

    DEPTNO DNAME                          LOC
---------- ------------------------------ -------------
        20 RESEARCH                       DALLAS

SCOTT@book01p> @ hash

HASH_VALUE SQL_ID        CHILD_NUMBER KGL_BUCKET PLAN_HASH_VALUE HASH_HEX   SQL_EXEC_START      SQL_EXEC_ID
---------- ------------- ------------ ---------- --------------- ---------- ------------------- -----------
1418564050 62m9tata8v4fk            0     102866      2852011669  548d91d2  2025-02-01 15:31:19    16777216

SYS@book> oradebug setmypid
Statement processed.
SYS@book> oradebug dump library_cache 4
Statement processed.
SYS@book> @t

TRACEFILE
--------------------------------------------------------------------------------
/u01/app/oracle/diag/rdbms/book/book/trace/book_ora_3514.trc

$ grep "^Bucket: #=102866" /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_3514.trc
Bucket: #=102866 Mutex=0x6c493990(1189705940992, 7, 0, 6)

--//0x6c493990-0x10 = 0x6c493980

SYS@book> @ opeek 0x6c493980 48 0
[06C493980, 06C4939B0) = 6995F5E0 00000000 6995F5E0 00000000 00000000 00000000 00000018 00000000 000191D2 00000000 659F8EE0 00000000
--//0x000191D2 = 102866,32-35字节是Bucket桶号102866.实际上是HASH_VALUE%2^_kgl_bucket_count * 256 = 1418564050%2^17 = 102866.

SYS@book> @ sharepool/shp4z 62m9tata8v4fk -1
HANDLE_TYPE            KGLHDADR         KGLHDPAR         C40                                        KGLHDLMD   KGLHDPMD   KGLHDIVC KGLOBHD0         KGLOBHD6           KGLOBHS0   KGLOBHS6   KGLOBT16   N0_6_16        N20   KGLNAHSH KGLOBT03        KGLOBT09
---------------------- ---------------- ---------------- ---------------------------------------- ---------- ---------- ---------- ---------------- ---------------- ---------- ---------- ---------- --------- ---------- ---------- ------------- ----------
parent handle address  000000006995F5E0 000000006995F5E0 select * from dept where deptno= 20               1          0          0 0000000062226DA8 00                     4064          0          0      4064       4064 1418564050 62m9tata8v4fk      65535
--//前面0-7,8-15字节分别是对象sql语句句柄的尾首指针。

3.测试该mutex的gets是否正确。

SYS@book> @ opeek 0x6c493980 48 0
[06C493980, 06C4939B0) = 6995F5E0 00000000 6995F5E0 00000000 00000000 00000000 0000001A 00000000 000191D2 00000000 659F8EE0 00000000
--//gets=0x1A

SCOTT@book01p> alter session set session_cached_cursors=0 ;
Session altered.

SCOTT@book01p> select * from dept where deptno= 20;

    DEPTNO DNAME                          LOC
---------- ------------------------------ -------------
        20 RESEARCH                       DALLAS

SCOTT@book01p> select * from dept where deptno= 20;

    DEPTNO DNAME                          LOC
---------- ------------------------------ -------------
        20 RESEARCH                       DALLAS

--//每执行1次使用opeek脚本查看1次。
SYS@book> @ opeek 0x6c493980 48 0
[06C493980, 06C4939B0) = 6995F5E0 00000000 6995F5E0 00000000 00000000 00000000 0000001B 00000000 000191D2 00000000 659F8EE0 00000000

SYS@book> @ opeek 0x6c493980 48 0
[06C493980, 06C4939B0) = 6995F5E0 00000000 6995F5E0 00000000 00000000 00000000 0000001C 00000000 000191D2 00000000 659F8EE0 00000000
--//gets数量从0000001B->0000001C.

4.测试该mutex的sleeps。
--//通过修改该值验证看看。
SYS@book> @ spid
==============================
SID                           : 16
SERIAL#                       : 37354
PROCESS                       : 3708
SERVER                        : DEDICATED
SPID                          : 3709
PID                           : 52
P_SERIAL#                     : 5
KILL_COMMAND                  : alter system kill session '16,37354' immediate;
PL/SQL procedure successfully completed.

$ rlgdb -f -p 3709   
....

(gdb) x /16wx 0x6c493980
0x6c493980:     0x6995f5e0      0x00000000      0x6995f5e0      0x00000000
0x6c493990:     0x00000000      0x00000000      0x0000001c      0x00000000
                                                                ~~~~~~~~~~
0x6c4939a0:     0x000191d2      0x00000000      0x659f8ee0      0x00000000
                                ~~~~~~~~~~
0x6c4939b0:     0x6c4939b0      0x00000000      0x6c4939b0      0x00000000
--//sleeps位置在地址0x6c49399c,顺便修改0x6c4939a4里面的保存信息。

(gdb) set *(int *)0x6c49399c=0xff
(gdb) set *(int *)0x6c4939a4=0xee
(gdb) x /16wx 0x6c493980
0x6c493980:     0x6995f5e0      0x00000000      0x6995f5e0      0x00000000
0x6c493990:     0x00000000      0x00000000      0x0000001d      0x000000ff
                                                                ~~~~~~~~~~~
0x6c4939a0:     0x000191d2      0x000000ee      0x659f8ee0      0x00000000
                                ~~~~~~~~~
0x6c4939b0:     0x6c4939b0      0x00000000      0x6c4939b0      0x00000000
--//注:oracle 21c版本已经不支持oradebug poke修改内存值。

SYS@book> @ opeek 0x6c493980 48 0
[06C493980, 06C4939B0) = 6995F5E0 00000000 6995F5E0 00000000 00000000 00000000 0000001D 000000FF 000191D2 000000EE 659F8EE0 00000000
--//验证修改正确!!                                                                    ~~~~~~~~          ~~~~~~~~

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

SYS@book> oradebug dump library_cache 4
Statement processed.

$ grep "^Bucket: #=102866" /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_3514_0001.trc
Bucket: #=102866 Mutex=0x6c493990(1189705940992, 30, 255, 6)
--//最后1个值都是6.前面1189705940992前面已经修改mutex的值,11g版本dump显示的都是0.在这里显示的dump会话的sid(前4个字节)
--//,后4个字节表示mutex持有的数量。
--//1189705940992 = 0x11500000000,补齐前面的0,0x0000011500000000,0x115 = 277,dump转储会话sid=277,大家可以自行验证。

SYS@book> @ opeek 0x6c493980 48 0
[06C493980, 06C4939B0) = 6995F5E0 00000000 6995F5E0 00000000 00000000 00000000 0000001E 000000FF 000191D2 00000000 659F8EE0 00000000
                                                                                        ~~~~~~~~          ~~~~~~~~
--//每次转储gets数量增加1,从0000001D->0000001E。sleeps=255,而转储后最后1个值变成6,而实际在内存里面是0,注:原来是0xee。

5.再看看最后8个字节(位于40-47字节):
--//前面猜测是一个地址,探究看看。

SYS@book> @ fchaz 659F8EE0
LOC KSMCHPTR           KSMCHIDX   KSMCHDUR KSMCHCOM           KSMCHSIZ KSMCHCLS   KSMCHTYP KSMCHPAR         KSMCHPTR_BEGIN   KSMCHPTR_END+1
--- ---------------- ---------- ---------- ---------------- ---------- -------- ---------- ---------------- ---------------- -----------------
SGA 00000000659F8ED0          1          1 KGLHBPVEC                88 perm              0 00000000659F8EB0 00000000659F8ED0 00000000659F8F28
--//00000000659F8ED0-00000000659F8EB0 = 0x20
--//KSMCHCOM=KGLHBPVEC ,KSMCHSIZ=88.

SYS@book> @ fchaz 00000000659F8EB0
no rows selected
--//通过堆描述符查询没有显示占用空间,KSMCHPAR=00000000659F8EB0。是否可以这样理解,建立相应chunk后,堆描述符占用的空间回
--//收了。

--//查看该chunk保存什么信息:
SYS@book> @ opeek 00000000659F8ED0 88 1
New tracefile_identifier = /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_3514_0003.trc
[0659F8ED0, 0659F8F28) = 00000059 00B38F00 17ADF554 00000000 0000000A 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ...
--//0x00000059 = 89 = 88+1.

--//查看跟踪文件:
*** 2025-02-01T16:08:19.549687+08:00 (CDB$ROOT(1))
Processing Oradebug command 'peek 0x00000000659f8ed0 88 1'
[0659F8ED0, 0659F8F28) = 00000059 00B38F00 17ADF554 00000000 0000000A ...
Dump of memory from 0x0659F8EE4 to 0x0659F8F28
0659F8EE0          00000000 00000000 00000000      [............]
0659F8EF0 00000000 00000000 00000000 00000000  [................]
        Repeat 2 times
0659F8F20 00000000 00000000      
--//如果不算前面16字节,仅仅剩下0000000A 表示怎么呢?主要是很难理解KGLHBPVEC缩略写表示什么?建立这样chunk用意何在。

$ grep "^Bucket: #=" /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_3514_0001.trc | head -4
Bucket: #=5 Mutex=0x6cfa14f0(1189705940992, 42, 0, 6)
Bucket: #=39 Mutex=0x6cfa1b50(1189705940992, 40, 0, 6)
Bucket: #=42 Mutex=0x6cfa1be0(1189705940992, 8, 0, 6)
Bucket: #=47 Mutex=0x6cfa1cd0(1189705940992, 8, 0, 6)

--//随便抽查几个检查都是类似,例子Bucket: #=5 Mutex=0x6cfa14f0(1189705940992, 42, 0, 6)。
SYS@book> @ opeek 0x6cfa14f0 32 0
[06CFA14F0, 06CFA1510) = 00000000 00000000 00000038 00000000 00000005 00000000 63838310 00000000

SYS@book> @ fchaz 63838310
LOC KSMCHPTR           KSMCHIDX   KSMCHDUR KSMCHCOM           KSMCHSIZ KSMCHCLS   KSMCHTYP KSMCHPAR         KSMCHPTR_BEGIN   KSMCHPTR_END+1
--- ---------------- ---------- ---------- ---------------- ---------- -------- ---------- ---------------- ---------------- -----------------
SGA 0000000063838300          1          1 KGLHBPVEC                88 perm              0 0000000063804000 0000000063838300 0000000063838358

SYS@book> @ fchaz 0000000063804000
no rows selected

SYS@book> select count(*) from x$ksmsp where KSMCHCOM='KGLHBPVEC' and KSMCHSIZ=88 and KSMCHCLS='perm';
  COUNT(*)
----------
     23174

--//按照这样推测,如果全部bucket都使用应该总数是2^17 = 131072.

$ cat m9.txt
DECLARE
   l_count PLS_INTEGER;
BEGIN
    FOR i IN 1..&&1
    LOOP
        EXECUTE IMMEDIATE 'select /*+ &&2 */ count(*) from dept where deptno = '||i  INTO l_count ;
    END LOOP;
END;
/
--//该脚本没有使用绑定变量,也就是尽可能地建立KSMCHCOM='KGLHBPVEC'类型的chunk。

$ zzdate ; seq 20 | xargs -P 20 -IQ sqlplus -s -l scott/book@book01p @ m9.txt 2e4 Q > /dev/null ; zzdate
trunc(sysdate)+16/24+18/1440+19/86400 1738397899.253119747
trunc(sysdate)+16/24+20/1440+13/86400 1738398013.374670218

SYS@book> select count(*) from x$ksmsp where KSMCHCOM='KGLHBPVEC' and KSMCHSIZ=88 and KSMCHCLS='perm';
  COUNT(*)
----------
    130873

--//已经非常接近了2^17= 131072.
--//修改m9.txt select 为Select.

$ zzdate ; seq 20 | xargs -P 20 -IQ sqlplus -s -l scott/book@book01p @ m9.txt 5e4 Q > /dev/null ; zzdate
trunc(sysdate)+16/24+43/1440+26/86400 1738399406.216715625
trunc(sysdate)+16/24+45/1440+22/86400 1738399522.855450824

SYS@book> select count(*) from x$ksmsp where KSMCHCOM='KGLHBPVEC' and KSMCHSIZ=88 and KSMCHCLS='perm';
  COUNT(*)
----------
    130898
--//嗯,还是不到131072.

SYS@book> select count(*) from x$ksmsp where KSMCHCOM='KGLHBPVEC' and KSMCHSIZ=88 ;
  COUNT(*)
----------
    131072

SYS@book> select count(*),KSMCHSIZ,KSMCHCLS from x$ksmsp where KSMCHCOM='KGLHBPVEC' and KSMCHSIZ=88 group by KSMCHSIZ,KSMCHCLS;
  COUNT(*)   KSMCHSIZ KSMCHCLS
---------- ---------- --------
       174         88 R-perm
    130898         88 perm
--//其中有174个是KSMCHCLS=R-perm类型,我估计我的测试环境共享内存太小,一部分使用保留池内存。
--//到此基本验证多出来的8字节保存的是地址信息,而且仅仅使用该bucket后才会出现地址不为0的情况。

4.小结:
--//关于mutex的结构,测试的结果如下:
--// 0- 7 字节是muext的值。
--// 8-11 字节是mutex gets的数量。
--//12-15 字节是mutex sleep的数量。
--//16-19 字节是Bucket桶号。
--//20-23 字节是转储看到的6,而opeek看都是0,表示什么不是很清楚。
--//mutex结构占用24字节。

--//前面的16字节保存的是对象句柄的地址。如果仅仅存在1个对象,两者相等(保存为父游标句柄地址)。如果存在多个对象会形成1
--//个双向链表,如果仅仅存在0个对象,两者等于mutex的地址-0x10。

--//后面的8字节对应的是某个地址,类型KSMCHCOM='KGLHBPVEC' and KSMCHSIZ=88。
--//16+24+8 = 48, 正好等于48字节。
posted @   lfree  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
历史上的今天:
2024-02-19 [20240219]建立完善sql_idx.sh脚本.txt
2019-02-19 [20190219]那个更快(11g).txt
点击右上角即可分享
微信分享提示