[20250202]21c library cache mutex的深入探究5.txt

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

[20250202]21c library cache mutex的深入探究5.txt --//前面的学习已经了解21c library cache mutex chunk分布的特点,再次总结如下: --//1个chunk 有256个mutex地址,占用12304,每个前面有16字节开头,许多chunk在内存分布上紧挨的。共计512个chunk。 --//在1个chunk内muetx每个偏移48字节. --//我的测试被分成3个大片:注:我在另外一台生产系统看到分成2个大片。 --//通过fchaz脚本查询对应的KSMCHPAR,没有信息输出。 --//问题来了,如果第一次执行一条sql语句,知道bucket桶号,oracle如何定位到相应mutex地址。 --//在11g下开始学习以为整个在一个chunk里面,这样知道基地址加上偏移量就可以知道buckect桶号就可以定位mutex地址。 --//实际上的情况在21c分布在存在于512个chunk中,前面的测试许多chunk在内存分布上紧挨的,分成3个大片。显然不能通过上面简单 --//计算定位mutex地址。 --//在11g下通过查询x$ksmmem,获得相应值,而21c下遇到问题,展开下面的分析。 1.环境: SYS@book> @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.简单介绍: SYS@book> select count(*),KSMCHPAR from x$ksmsp where KSMCHCOM='KGLSG'  and KSMCHSIZ=12304 group by KSMCHPAR;   COUNT(*) KSMCHPAR ---------- ----------------         31 000000006CC04000        339 000000006C804000        142 000000006C434000 --//Sum = 512。 --//前面的测试在一个chunk内每个mutex地址相邻相差48字节,48*256+16 = 12304,也就是1个chunk保存256个mutex地址。 SYS@book> @ fchaz 000000006CC04000 no rows selected SYS@book> @ fchaz 000000006C804000 no rows selected SYS@book> @ fchaz 000000006C434000 no rows selected --//堆描述符并没有占用空间,我个人认为启动时存在的,建立library cache mutex的chunk后删除了。 SYS@book> select * from (select * from x$ksmmem order by addr desc) where rownum=1; ADDR                   INDX    INST_ID     CON_ID KSMMMVAL ---------------- ---------- ---------- ---------- ---------------- 000000006093DFA0    1211380          1          1 00 --//使用x$ksmmem查询的最大地址是000000006093DFA0.而实际上sga占用内存分布如下: $ pmap -x $(pgrep pmon) | egrep  -i "sysv|^Address" Address           Kbytes     RSS   Dirty Mode  Mapping 0000000060000000   10240       0       0 rw-s- SYSV00000000 (deleted) ~~~~~~~~~~~~~~~~ 0000000060c00000  770048       0       0 rw-s- SYSV00000000 (deleted) 000000008fc00000    8192       0       0 rw-s- SYSV00000000 (deleted) --//使用x$ksmmem仅仅查询到下划线的内存区域,不能再使用它查询整个sga。 --//不过在11g的测试中已经知道其内存地址就在bucket =0 的mutex地址前面的。 --//注:11g 下在同1个chunk,21c情况不是。 3.分析: --//转储library_cache: SCOTT@book01p> select /*+ 9 */ count(*) from dept where deptno = 93834;   COUNT(*) ----------          0 SCOTT@book01p> @ hash HASH_VALUE SQL_ID        CHILD_NUMBER KGL_BUCKET PLAN_HASH_VALUE HASH_HEX   SQL_EXEC_START      SQL_EXEC_ID ---------- ------------- ------------ ---------- --------------- ---------- ------------------- ----------- 3403546624 as3g00v5dw000            0          0      2236899148  cade0000  2025-02-02 15:19:04    16777221 SYS@book> oradebug setmypid Statement processed. SYS@book> oradebug dump library_cache 4 Statement processed. $ grep "^Bucket:" /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_10770.trc | head -4 Bucket: #=0 Mutex=0x6cfa1400(1125281431552, 9, 0, 6) Bucket: #=5 Mutex=0x6cfa14f0(1125281431552, 4, 0, 6) Bucket: #=17 Mutex=0x6cfa1730(1125281431552, 8, 0, 6) Bucket: #=39 Mutex=0x6cfa1b50(1125281431552, 4, 0, 6) --//Bucket: #=0 Mutex=0x6cfa1400 --//0x6cfa1400-0x10 = 0x6cfa13f0 SYS@book> @ fchaz 0x6cfa1400 LOC KSMCHPTR           KSMCHIDX   KSMCHDUR KSMCHCOM           KSMCHSIZ KSMCHCLS   KSMCHTYP KSMCHPAR         KSMCHPTR_BEGIN   KSMCHPTR_END+1 --- ---------------- ---------- ---------- ---------------- ---------- -------- ---------- ---------------- ---------------- ----------------- SGA 000000006CFA13E0          1          1 KGLSG                 12304 perm              0 000000006CC04000 000000006CFA13E0 000000006CFA43F0 --//0x000000006CFA13E0-0x1 = 0x6cfa13df SYS@book> @ fchaz 000000006CFA13df LOC KSMCHPTR           KSMCHIDX   KSMCHDUR KSMCHCOM           KSMCHSIZ KSMCHCLS   KSMCHTYP KSMCHPAR         KSMCHPTR_BEGIN   KSMCHPTR_END+1 --- ---------------- ---------- ---------- ---------------- ---------- -------- ---------- ---------------- ---------------- ----------------- SGA 000000006CFA03C0          1          1 KGLSG                  4128 perm              0 000000006CC04000 000000006CFA03C0 000000006CFA13E0 --//在Bucket: #=0前面的chunk大小KSMCHSIZ=4128,KSMCHCOM=KGLSG(类型与后面的chunk一样)。 --//如果每个地址占用8个字节,共计512个,4128-512*8 = 32。基本猜测正确,验证看看。 SYS@book> @ opeek 000000006CFA03C0 64 1 New tracefile_identifier = /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_3412_0005.trc [06CFA03C0, 06CFA0400) = 00001021 00B38F00 17ADF8D0 00000000 6CFA03E0 00000000 000016E8 00020000 6CFA13F0 00000000 6CFA4400 00000000 6CFA7410 00000000 ...                                                                                                  ~~~~~~~~          ~~~~~~~~~         ~~~~~~~~ --//0x00001021 = 4129 = 4128+1 ,看来chunk的开头前4字节保存的是chunk大小+1. --//注意看下划线值(前面占用32字节),正好等于0x6cfa1400-0x10 = 0x6cfa13f0。 --//0x6CFA4400-0x6CFA13F0 = 12304 --//0x6CFA7410-0x6CFA4400 = 12304 --//前后相减正好等于12304. --//实际上很简单在一个chunk里面记录了一张表或者讲一个数组,记录数量为2^_kgl_bucket_count,每个占8字节(我的OS 64位系统),相 --//当于N*256的mutex地址(N=0到511),假设知道基地址A后,如果知道bucket值.使用bucket/256 取整就可以定位 该地址B 保存在 --//A + trunc(bucket/256)*8的位置,再通过bucket%256 * 40 + B , 该位置就保存了该bucket的library cache mutex的地址。 4.验证分成3个大片: SYS@book> @ opeek 000000006CFA03C0 4128 1 New tracefile_identifier = /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_3412_0007.trc [06CFA03C0, 06CFA13E0) = 00001021 00B38F00 17ADF8D0 00000000 6CFA03E0 00000000 0000188E 00020000 6CFA13F0 00000000 6CFA4400 00000000 6CFA7410 00000000 ... $ sed -n "/^06CFA03E0/,/^06CFA13D0/p" /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_3412_0007.trc | awk '{print $2"\n"$4}' > d2.txt $ head -4 d2.txt 6CFA13F0 6CFA4400 6CFA7410 6CFAA420 $ wc d2.txt  512  512 4608 d2.txt $ awk 'NR==1{a=$1} NR>1{ print $1,a,strtonum("0x"$1)-strtonum("0x"a);a=$1}'  d2.txt | head -10 6CFA4400 6CFA13F0 12304 6CFA7410 6CFA4400 12304 6CFAA420 6CFA7410 12304 6CFAD430 6CFAA420 12304 6CFB0440 6CFAD430 12304 6CFB3450 6CFB0440 12304 6CFB6460 6CFB3450 12304 6CFB9470 6CFB6460 12304 6CFBC480 6CFB9470 12304 6CFBF490 6CFBC480 12304 $ awk 'NR==1{a=$1} NR>1{ print $1,a,strtonum("0x"$1)-strtonum("0x"a);a=$1}'  d2.txt | awk '{print $3}'| uniq -c      30 12304       1 -8353184     338 12304       1 -8156448     141 12304 --//与前面的select count(*),KSMCHPAR from x$ksmsp where KSMCHCOM='KGLSG'  and KSMCHSIZ=12304 group by KSMCHPAR;输出可以对上。 5.顺便找一条实际的sql语句测试看看。 SCOTT@book01p> select * from dept where deptno = 40 ;     DEPTNO DNAME                          LOC ---------- ------------------------------ -------------         40 OPERATIONS                     BOSTON SCOTT@book01p> @ hash HASH_VALUE SQL_ID        CHILD_NUMBER KGL_BUCKET PLAN_HASH_VALUE HASH_HEX   SQL_EXEC_START      SQL_EXEC_ID ---------- ------------- ------------ ---------- --------------- ---------- ------------------- -----------   61084640 2k056r41u84z0            0       5088      2852011669   3a413e0  2025-02-02 16:22:05    16777216 --//KGL_BUCKET=5088,计算就是使用HASH_VALUE % (2^_kgl_bucket_count * 256),缺省_kgl_bucket_count=9.61084640%2^17 = 5088 --//5088/256 = 19.875,取整就是19,取模 5088%256 = 224 ,224 = 0xe0 $ sed -n "20,20p" d2.txt 6CFDA520 --//注意从0开始计数,相当于取20行的记录。 --///6CFDA520+0x30*0xe0  = 0x6cfdcf20 SYS@book> @ opeek 0x6cfdcf20 48 0 [06CFDCF20, 06CFDCF50) = 671C92D8 00000000 671C92D8 00000000 00000000 00000000 0000000B 00000000 000013E0 00000000 64CEEB50 00000000 SYS@book> @ sharepool/shp4z 2k056r41u84z0 -1 '' HANDLE_TYPE            KGLHDADR         KGLHDPAR         C40                                        KGLHDLMD   KGLHDPMD   KGLHDIVC KGLOBHD0         KGLOBHD6           KGLOBHS0   KGLOBHS6   KGLOBT16   N0_6_16        N20   KGLNAHSH KGLOBT03        KGLOBT09 ---------------------- ---------------- ---------------- ---------------------------------------- ---------- ---------- ---------- ---------------- ---------------- ---------- ---------- ---------- --------- ---------- ---------- ------------- ---------- parent handle address  00000000671C92D8 00000000671C92D8 select * from dept where deptno = 40              1          0          0 00000000679A7B48 00                     4064          0          0      4064       4064   61084640 2k056r41u84z0      65535 --//parent handle address=00000000671C92D8,与opeek的输出前面16字节 能够对上。 --//0x000013E0  = 5088 ,正好等于bucket桶号。 6.小结: --//实际上很简单在一个chunk里面记录了一张表或者讲一个数组,记录数量为2^_kgl_bucket_count,每个占8字节(我的OS 64位系统),相 --//当于N*256的mutex地址(N=0到511),假设知道基地址A后,如果知道bucket值.使用bucket/256 取整就可以定位 该地址B 保存在 --//A + trunc(bucket/256)*8的位置,再通过bucket%256 * 40 + B , 该位置就保存了该bucket的library cache mutex的地址。

相关推荐