HEAP结构与ORA-4031

Oracle的各种内存组织都是以HEAP形式的,每个HEAP包含一个HEAP句柄和一系列的内存EXTENT,每个EXTENT包含了一系列的连续的CHUNK。当一个HEAP创建的时候,首先通过kghini调用来初始化HEAP句柄。一个HEAP句柄包括一组FREE LIST BUCKETS和相应的SIZE参数。调用kghini()的重要参数包括:heap的extent大小、heap的freelist桶的数量、分配大小、分配类型等。FREE LIST上链接了相同分配类型的的CHUNK。当正在使用的CHUNK释放的时候,会被放入到大小小于等于该CHUNK的FREE LIST上去,在同一个FREE LIST里,CHUNK不按照大小排序。比如:

可以看出,其中Bucket 0是存放所有小余76字节的CHUNK,Bucket 10存放所有大于32780字节的CHUNK。其他Bucket存放的CHUNK都是大于其SIZE大小,小于下一个Bucket的SIZE大小的CHUNK。另外一点我们要注意的是,Bucket中的CHUNK不是按照大小排序的。上面的例子是8.1.5的,不同的版本下,Bucket的数量会有所不同。

从共享池分配空间通过调用kghalo()来实现,这个调用返回指向CHUNK空间的指针。分配的空间的大小通过REQ_SIZE参数传递,但是堆管理会根据判断分配被称为ACTUAL_SIZE的空间,ACTUAL_SIZE可能比REQ_SIZE大或者小,不过并不是无规律的。从共享池分配空间的基本顺序如下:

首先搜索FREELIST上是否存在FREE的CHUNK;

如果没找到,第二步查找是否有RECREATABLE的CHUNK可以释放。已经使用的CHUNK被链接到LRU上,LRU链表中

当出现ORA - 04030错误,即尝试分配23201184字节时进程内存不足,可从以下方面考虑解决办法: ### 调整SGA和PGA参数 SGA(System Global Area)是Oracle实例启动时分配的一组共享内存结构,PGA(Program Global Area)是每个Oracle服务器进程或后台进程分配的非共享内存区域。可以通过调整这两个参数来增加可用内存。 参考示例,可查看当前SGA和PGA的设置: ```sql SQL> show parameter sga NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ lock_sga boolean FALSE pre_page_sga boolean FALSE sga_max_size big integer 36G sga_target big integer 36G SQL> show parameter pga_aggregate_target NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ pga_aggregate_target big integer 10G ``` 根据实际情况,适当增大`sga_max_size`、`sga_target`和`pga_aggregate_target`的值。例如: ```sql alter system set sga_max_size = 40G scope=spfile; alter system set sga_target = 40G scope=spfile; alter system set pga_aggregate_target = 12G scope=spfile; ``` 修改完成后,需要重启数据库使参数生效。 ### 启用和调整自由堆参数 可以尝试启用和调整自由堆相关参数,参考示例如下: ```sql alter system set "_use_realfree_heap"=TRUE scope=spfile; alter system set "_realfree_heap_pagesize"=200000 scope=spfile; ``` 同样,修改完成后需要重启数据库使参数生效。 ### 优化SQL语句和业务逻辑 频繁出现ORA - 04030错误可能是由于某些SQL语句或业务逻辑不合理,导致内存占用过高。可以对执行频繁、占用资源较多的SQL语句进行优化,例如添加合适的索引、避免全表扫描等。 ### 检查和清理无用的会话和进程 过多的活动会话和进程会占用大量的内存资源。可以使用以下SQL语句查看当前活动的会话和进程,并根据情况进行清理: ```sql SELECT s.sid, s.serial#, p.spid FROM v$session s, v$process p WHERE s.paddr = p.addr AND s.status = 'ACTIVE'; ``` 对于不需要的会话,可以使用`ALTER SYSTEM KILL SESSION`语句进行终止: ```sql ALTER SYSTEM KILL SESSION 'sid,serial#'; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值