Oracle ‘KGH: NO ACCESS’ 究竟是什么?
相信有时数据库Oracle出现ora-4031时trace中显示’KGH: NO ACCESS’出现在top 10,或检查v$sgastat可以发现’KGH: NO ACCESS’ 区占用较大空间, 主要是启用了ASMM或AMM时,从shared pool或streams pool 延迟切换内存给buffer cache, 以增加buffer cache大小时,原子池中会标记为’KGH: NO ACCESS’, 下面简单的记录。
How To Prevent The Growth Of The Component ‘KGH: NO ACCESS’ In The Shared Pool When ASMM Is Enabled (Doc ID 451960.1)
KGH: NO ACCESS’ refers to granules that are in transit with ASMM i.e memory being reassigned from the Shared Pool to the Database Buffer Cache and vice-versa.
This memory component in the Shared Pool marked as ‘KGH: NO ACCESS’ is used by the Buffer Cache.
我们都知道在启用ASMM时,SGA的共享子内存区如Shared Pool, Database Buffer Cache, Large Pool, Java Pool and Streams Pool可以自动跨subpool调整, 但是REDO log buffer pool和fixed SGA是固定的。 而调整最多的是shared pool和buffer cache, 那在调整后在如从shared pool中shrink再给buffer cache grow (DEFERRED),标记它们 作为 “KGH: NO ACCESS” 没有其他人会碰它们,则标记相应的 条目添加到 V$SGA_RESIZE_OPS 中的 DEFERRED,并通知buffer cache 可供使用的新内存位置。这过程会在v$sgastat中看到shared pool中的”KGH: NO ACCESS”在增加,用于给buffer cache使用。 是的,没看错,当使用ASMM时,有可能data block的buffer cache在shared pool中。早在10几年前Tanelpoder就写过两篇:
KGH: NO ACCESS allocations in V$SGASTAT – buffer cache within shared pool!
KGH: NO ACCESS – Buffer cache inside streams pool too!
从x$ksmsp 中可以观察到该内存区的位置(生产库不要查询该操作,查询会锁定共享池). 此视图中为从它分配的每个内存块(以及空闲块)都有一行,如果你的共享池很大,并且里面有很多 chunk,那么链表遍历将花费很长时间,因此锁存器将保持很长时间。当共享池闩锁被持有时,会出现大量的shared pool相关的等待,导致 数据库hang死。
SELECT ksmchcom,ksmchptr,ksmchsiz,ksmchcls FROM x$ksmsp -- do not query from this view in production!!! WHERE ksmchcom = 'KGH: NO ACCESS' AND rownum = 1; -- Find in buffer cache SELECT 2 dbarfil, dbablk, obj, ba, state --<-- dbarfil = relative file number, dbablk = block number, obj = data object id 3 FROM 4 x$bh --<-- X$BH lists all initialized buffers in buffer cache 5 WHERE 6 to_number(rawtohex(ba),'XXXXXXXXXXXXXXXX') --<-- BA is the "buffer address", actual buffer location in SGA memory 7 BETWEEN 8 to_number('[ KSMCHPTR]','XXXXXXXXXXXXXXXX') 9 AND to_number('[ KSMCHPTR]','XXXXXXXXXXXXXXXX') + [KSMCHSIZ]- 1 10 /
同样从如果stream pool比较空间时,也会给buffer cache使用。
select last_oper_type, last_oper_mode from v$sga_dynamic_components where component = 'streams pool';
在跨池给buffer cache使用,以增加buffer cache大小,在还没有完成granule 完整的 granule 切换,如stream pool还是shared pool时都会有该内存区,收缩操作处于 DEFERRED 状态。在其堆头中将它可以刷新的所有内容标记为 “KGH: NO ACCESS”,并将这些块移交给BUffer cache 使用.
计算“KGH: NO ACCESS”该块的结束地址(起始地址 + 大小 -1 = 结束地址)KSMCHPTR+KSMCHSIZ-1,使用该地址范围查询 X$BH,看看是否/有多少缓冲区缓存缓冲区被放置在其中.
select ksmchidx,ksmchdur,ksmchcom,ksmchptr,ksmchsiz,ksmchcls from x$ksmsst where ksmchcom = 'KGH: NO ACCESS'; SQL> @calc KSMCHPTR+KSMCHSIZ-1 select count(*) from x$bh where rawtohex(ba) between xx and xx;
减少该内存区的方法。
1, 禁用ASMM
2, 给每个subpool指定下限值,让子池如shared pool给buffer cache调整的越小,那自然“KGH: NO ACCESS”也就越小。
对不起,这篇文章暂时关闭评论。