数据库参数 PGA_AGGREGATE_LIMIT 限制进程大小

在自动化 PGA 内存管理模式下,Oracle 数据库通过动态控制分配到工作区的 PGA 内存量来尝试遵从 PGA_AGGREGATE_TARGET 值。但是,有时因为以下原因,PGA 内存使用量可能会超过 PGA_AGGREGATE_TARGET 设置:

  • PGA_AGGREGATE_TARGET 设置起到的是目标的作用,而非限制。

  • PGA_AGGREGATE_TARGET 仅控制可优化部分内存的分配。

使用大量 PGA 可能会导致高交换率。出现这种情况时,系统可能会无法响应,并且不稳定。这种时候需要考虑使用 PGA_AGGREGATE_LIMIT 初始化参数限制整体 PGA 使用量。

12c 引入了新的参数 PGA_AGGREGATE_LIMIT 以允许数据库管理员限制 pga 内存使用总量。

使用 PGA_AGGREGATE_LIMIT初始化参数可以为 PGA 内存使用量指定硬性限制。如果超过了 PGA_AGGREGATE_LIMIT 值,则 Oracle 数据库按照以下顺序,中断或者终止使用了最多不可优化 PGA 内存的会话或进程:

  • 中止使用了最多不可优化 PGA 内存的会话调用。

  • 如果 PGA 内存使用量仍超过 PGA_AGGREGATE_LIMIT,则终止使用了最多不可优化 PGA 内存的会话和进程。

使用最多不可优化内存会话的调用将被中止。并行查询将被视为一个单元。如果 PGA 内存使用总量仍超过限制,则将终止使用最多不可优化内存的会话。

不会对除作业队列进程之外的 SYS 进程和后台进程执行这一部分中所述的任何操作。取而代之的操作是,如果它们使用了最多不可优化内存,则会定期将其 PGA 使用量的简短摘要写入到跟踪文件中。

不可调的 PGA 内存就像每个会话、每个打开/活动游标、PL/SQL 或 Java 内存的上下文信息。
可调 PGA 内存是为密集型内存 SQL 运算符分配的内存,例如排序、哈希连接、分组、位图合并和位图索引创建。

PGA 不是 Oracle 中唯一的内存“全局区域”。还有 MGA(Managed Global Area)和 DGA(Dynamic Global Area)(当然还有 SGA):

MGA 或 Managed Global Area:允许“较小的一组”进程(甚至所有进程)在某段时间(通常是查询)内共享地址空间(命名空间)。

DGA 或 Dynamic Global Area:允许在 PGA 初始化期间初始化并且在运行时不可修改的变量池。
它们不会跨进程更改,但需要在 SGA 初始化之前可用。因此,它们可作为全局变量供其他进程使用。

MGA 和 DGA 至少从 12.1 开始就存在了。但是只有在最近的版本中,数据库组件才开始使用它,所以这个池可能比 12.1.0.2 上的要大得多。我们开始在18c 的 v$pgastat 中统计 MGA 和 DGA。

由于 MGA 和 DGA 在 Oracle 进程之间共享,因此它们不能归属于单个进程。
所以 v$process 和 v$sesstat 不能包含它们。它们仅计入 v$pgastat,其中一部分计入“使用中的总 PGA”。

您可以运行以下查询以查看这些池的属性,例如(注意“PGA”后面的空格):


SQL> col name for a40
SQL> select * from v$pgastat where name like '%GA%' and name not like '%PGA %';

NAME VALUE UNIT CON_ID
---------------------------------------- ---------- ------------ ----------
DGA allocated (under PGA) 10566656 bytes 0
maximum DGA allocated 12103680 bytes 0
MGA allocated (under PGA) 0 bytes 0
maximum MGA allocated 0 bytes 0

一般来说,最新版本的内存使用率总是会更高,因此在从 12.1.0.2 升级到 19c 时,可预期会看到更多的 PGA 分配。

PGA_AGGREGATE_LIMIT 初始化参数动态设置为 PGA 内存的实例范围硬性限制。由于该参数根据内存情况的变化做出响应,您无需显式设置参数值。默认情况下,PGA_AGGREGATE_LIMIT被设置为:

在Oracle 12.1版本: PGA_AGGREGATE_LIMIT默认为如下值中的最大者:

  • 2 GB
  • 200% 的 PGA_AGGREGATE_TARGET
  • (PROCESSES 初始化参数设置值)* 3 MB

该参数不会超过物理内存大小减去总 SGA 大小的 120%。

在Oracle 12.2版本: PGA_AGGREGATE_LIMIT的默认值为:

* 如果设置了MEMORY_TARGET, 那么PGA_AGGREGATE_LIMIT默认值为MEMORY_MAX_TARGET的值.
* 如果MEMORY_TARGET没有设置, 那么PGA_AGGREGATE_LIMIT默认值为 200%的PGA_AGGREGATE_TARGET值.
* 如果MEMORY_TARGET没有设置, 并且PGA_AGGREGATE_TARGET被显式的设置为0, 那么PGA_AGGREGATE_LIMIT的默认值为90%的物理内存减去SGA的大小.
在以上所有情况中,默认的PGA_AGGREGATE_LIMIT至少是2GB 并且至少是数据库参数PROCESSES乘以3MB的大小. 在 Oracle 版本 18c 及更高版本中,它应该是 Oracle RAC 实例的 PROCESSES 参数的至少 5MB 倍。

注意: 如果指定PGA_AGGREGATE_LIMIT的值为0,则表示实例所使用的 PGA 内存总量没有限制。

在 Oracle 版本 18c 及更高版本中:

MGA(Managed Global Area)在 PGA 之外进行计算。
这实际上意味着在 18c 及以上版本中必须增加 PGA 大小以适应 MGA。

一个经验法则是:

PGA_AGGREGATE_LIMIT = (原始 PGA_AGGREGATE_LIMIT 值) + ((最大连接进程数) * 4M)

但是,有一种更“科学”的方法可以根据数据库中可检索的指标来确定该值(有关参考,请参阅 Note 2808761.1):

((实例生命周期内使用的最大 PGA) + ((实例生命周期内连接的最大进程数) * 5M)) * 1.1

此问题的另一个影响是客户可能会报告升级到 18c 及更高版本后 PGA 使用量增加。
这是意料之中的,因为 MGA 现在已从 PGA 中扣除。

 
PGA_AGGREGATE_LIMIT 初始化参数可以动态设置;并不需要数据库重新启动。可以设置 PGA_AGGREGATE_LIMIT 的值,不论是否使用了自动内存管理。

后台进程 CKPT 每三秒检查一次内存用量是否超过了 PGA_AGGREGATE_LIMIT 初始化参数的值。如果达到或超过了限制,则此进程中断使用最多不可优化 PGA 内存的会话调用。如果这些会话仍没有释放足够内存,则终止它们。

请注意,由于 pga 值仅每三秒检查一次,因此 pga 内存有可能超过 PGA_AGGREGATE_LIMIT。此外,如果在此期间该 pga 值减少到限制之下,则将不会捕获在这三秒间隔内超过限制的情况。如果进程在三秒的间隔内快速分配然后释放内存,则可能会出现这种情况。

示例:

如下的信息会被写入到CKPT trace 文件,

PGA LIMIT: pid 317111 is ineligible for an ORA-4036 interrupt
System processes and most background processes cannot receive ORA-4036
interrupts. When they are contributing to the instance exceeding
PGA_AGGREGATE_LIMIT, they will periodically dump their PGA usage.
PGA LIMIT: pid 317124 is a top contributor to going over PGA_AGGREGATE_LIMIT
PGA LIMIT: pid 317124 is ineligible for an ORA-4036 interrupt
PGA LIMIT: pid 317120 is a top contributor to going over PGA_AGGREGATE_LIMIT
PGA LIMIT: pid 317120 is ineligible for an ORA-4036 interrupt

如果达到了 PGA_AGGREGATE_LIMIT 值,则将报告如下错误。

ORA-04036: PGA memory used by the instance exceeds PGA_AGGREGATE_LIMIT

Cause: Private memory across the instance exceeded the limit specified in the PGA_AGGREGATE_LIMIT initialization parameter. The largest sessions using Program Global Area (PGA) memory were interrupted to get under the limit.

Action: Increase the PGA_AGGREGATE_LIMIT initialization parameter or reduce memory usage.

示例:

 此示例将展示使用 pl/sql 填充内存中数组可以超过 pga_aggregate_limit 的值。

首先请查看当前 pga_aggregate_target。由于 pl/sql 内存区不是 pga 目标控制的可优化区域,进程 pga 将超过此值。

-- V$PGASTAT 的 PGA 统计信息:
-- 显示自实例启动以来分配的最大 pga 总量

select name, ROUND(value/1024/1024) as Mbytes from v$pgastat
where name in ('maximum PGA allocated','aggregate PGA target parameter','aggregate PGA auto target');

NAME                         Mbytes
---------------------- ------------
aggregate PGA target p          208
arameter

aggregate PGA auto tar          138
get

maximum PGA allocated           119
 

 请注意 pga_aggregate_limit 显式设置为 512M。

select con_id, name as Parameter, value/1024/1024 as Mbytes from V$SYSTEM_PARAMETER
where name in ('pga_aggregate_target','memory_target','memory_max_target','sga_max_size','sga_target','pga_aggregate_limit','processes')
order by name;

CON_ID PARAMETER                            Mbytes
------ ------------------------------ ------------
     0 memory_max_target                       600
     0 memory_target                           600
     0 pga_aggregate_limit                     512
     0 pga_aggregate_target                      0
     0 processes                                 0
     0 sga_max_size                            600
     0 sga_target                                0

 

运行这个过程的会话收到此错误:

ERROR at line 1:
ORA-04036: PGA memory used by the instance exceeds PGA_AGGREGATE_LIMIT

针对 V$PROCESS 的查询显示进程在 ckpt进程捕获到这种情况并中止其对内存的调用之前,在 3 秒时间内增长到 2.5G 大小。

SET PAGESIZE 120
COLUMN con_id HEADING 'CON_ID' FORMAT 9999999
COLUMN spid HEADING 'OSpid' FORMAT a8
COLUMN pid HEADING 'Orapid' FORMAT 999999
COLUMN sid HEADING 'Sess id' FORMAT 99999
COLUMN serial# HEADING 'Serial#' FORMAT 999999
COLUMN status HEADING 'Status' FORMAT a8
COLUMN pga_alloc_mem HEADING 'PGA alloc' FORMAT 99,999,999,999
COLUMN pga_used_mem HEADING 'PGA used' FORMAT 99,999,999,999
COLUMN username HEADING 'Oracle user' FORMAT a12
COLUMN osuser HEADING 'OS user' FORMAT a12
COLUMN program HEADING 'Program' FORMAT a20

SELECT p.con_id,
p.spid,
p.pid,
s.sid,
s.serial#,
s.status,
p.pga_alloc_mem,
p.pga_used_mem,
s.username,
s.osuser,
s.program
FROM v$process p, v$session s
WHERE s.paddr( + ) = p.addr
ORDER BY p.pga_alloc_mem DESC;

CON_ID OSpid     Orapid Sess id Serial# Status      PGA alloc     PGA used      PGA Max PNAME oracleuser   OS user      Program
------ -------- ------- ------- ------- -------- ------------ ------------ ------------ ----- ------------ ------------ ------------------------
     4 5349          33     258      41 INACTIVE            3            2        2,536       SYSTEM       oracle       sqlplus@localhost.locald
                                                                                                                        omain (TNS V1-V3)

 

alert.log 显示以下错误。

Errors in file /u01/app/oracle/diag/rdbms/cdb1/cdb1/trace/cdb1_ora_5349.trc  (incident=79479):
ORA-04036: PGA memory used by the instance exceeds PGA_AGGREGATE_LIMIT
Incident details in: /u01/app/oracle/diag/rdbms/cdb1/cdb1/incident/incdir_79479/cdb1_ora_5349_i79479.trc
Dumping diagnostic data in directory=[cdmp_20130128072143], requested by (instance=1, osid=5349), summary=[incident=79479].
 

进程的跟踪文件显示与导致此错误的进程相关的信息。

通过显示的服务名您可以知道是哪个容器发生了错误。

跟踪文件还提供了摘要 heap dump(堆转储)。在本例中,主堆具有 2159MB 的“koh-kghu call”。在该堆中,子堆包括 2154 MB 的“pl/sql vc2”。可以使用这些内容在 MOS 上搜索有关这些分配的任何已知问题。诸如这样一些与 pl/sql 相关的分配通常是 pl/sql 程序一次性将大量数据加载到内存中造成的。在这样的情况下,应该变更程序,一次将有限数量的记录加载到内存中。替代方法是允许这样大的分配并增加 pga_aggregate_limit 的值

*** SERVICE NAME:(pdb1.example.com) 2013-01-28 07:44:27.902  <===-----------请注意指示哪个容器出现错误的服务的名称。
*** MODULE NAME:(SQL*Plus) 2013-01-28 07:44:27.902
*** ACTION NAME:() 2013-01-28 07:44:27.902
*** CONTAINER ID:(4) 2013-01-28 07:44:27.902
 

*** TRACE FILE RECREATED AFTER BEING REMOVED ***

Process may have gone over pga_aggregate_limit
Just allocated 65536 bytes
Dumping short stack in preparation for potential ORA-4036
----- Abridged Call Stack Trace -----
ksedsts()+313<-ksm_pga_limit_short_stack()+456<-ksm_check_over_limit()+540<-ksmapg()+351<-kghgex()+1426<-kghfnd()+745<-kghalo()+693<-kghgex()
+401<-kghalf()+403<-kghualloc()+794<-kohalmc()+295<-kohalc()+110<-plsm0vc_rsz()+197<-pevm_MOVC_i()+1021<-pfrinstr_MOVC()+52
<-pfrrun_no_tool()+60<-pfrrun()+809<-plsql_run()+617<-peicnt()+287<-kkxexe()+789
----- End of Abridged Call Stack Trace -----
=======================================
PRIVATE MEMORY SUMMARY FOR THIS PROCESS
---------------------------------------
******************************************************
PRIVATE HEAP SUMMARY DUMP
2161 MB total:
  2161 MB commented, 261 KB permanent
   481 KB free (256 KB in empty extents),
    2159 MB,   1 heap:    "koh-kghu call  "            1 KB free held  <=============指示在 pga 中使用内存的命名内存分配
------------------------------------------------------
Summary of subheaps at depth 1
2155 MB total:
  2155 MB commented, 104 KB permanent
   295 KB free (20 KB in empty extents),
    2154 MB, 138274 chunks:  "pl/sql vc2                " <--------------------指示 pga heap(堆)中包含的子堆内存分配

*** 2013-01-28 07:44:28.045
Incident 79480 created, dump file: /u01/app/oracle/diag/rdbms/cdb1/cdb1/incident/incdir_79480/cdb1_ora_5349_i79480.trc
ORA-04036: PGA memory used by the instance exceeds PGA_AGGREGATE_LIMIT

*********START PLSQL RUNTIME DUMP************
***Got internal error Exception caught in pl/sql run-time while running PLSQL***
***Got ORA-4036 while running PLSQL***
PROCEDURE SYSTEM.FILL_MEMORY:

意外事件文件显示程序堆栈及行号

Dump continued from file: /u01/app/oracle/diag/rdbms/cdb1/cdb1/trace/cdb1_ora_5349.trc
ORA-04036: PGA memory used by the instance exceeds PGA_AGGREGATE_LIMIT

========= Dump for incident 79480 (ORA 4036) ========

*** 2013-01-28 07:44:28.045
dbkedDefDump(): Starting incident default dumps (flags=0x2, level=3, mask=0x0)
----- Current SQL Statement for this session (sql_id=gqbtzt92rm1ck) -----
BEGIN fill_memory(2680000); END;
----- PL/SQL Stack -----
----- PL/SQL Call Stack -----
  object      line  object
  handle    number  name
0x77335850         7  procedure SYSTEM.FILL_MEMORY <-------程序的行号
0x77238760         1  anonymous block

----- Call Stack Trace -----

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值