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

来源:这里教程网 时间:2026-03-03 21:33:29 作者:

[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字节。

相关推荐