PGA_AGGREGATE_LIMIT - Set Hard PGA Memory Limit in Oracle 12c+
PGA_AGGREGATE_LIMIT
Section titled “PGA_AGGREGATE_LIMIT”Overview
Section titled “Overview”PGA_AGGREGATE_LIMIT sets a hard upper bound on the total amount of PGA memory that all Oracle processes can consume simultaneously. Introduced in Oracle 12c, it acts as a safety net above PGA_AGGREGATE_TARGET: while the target is a soft goal that Oracle tries to respect, the limit is enforced unconditionally. When total PGA allocation reaches this limit, Oracle identifies and terminates the calls — or, in extreme cases, the sessions — with the largest PGA footprints to bring total usage back below the ceiling. This protects the operating system from being starved of memory by runaway sort or hash join operations.
Parameter Type: Dynamic (ALTER SYSTEM) Default Value: The greater of 2GB or 200% of PGA_AGGREGATE_TARGET (with a floor of 2GB) Valid Range: 0 (disabled) or any value >= 2GB and >= PGA_AGGREGATE_TARGET Available Since: Oracle 12c (12.1.0.1) Modifiable: Yes — SCOPE=BOTH PDB Modifiable: Yes (within CDB limits)
Configuration
Section titled “Configuration”Viewing Current Value
Section titled “Viewing Current Value”-- Check current PGA_AGGREGATE_LIMIT settingSELECT name, value/1024/1024 AS value_mb, isdefault, ismodified, descriptionFROM v$parameterWHERE name = 'pga_aggregate_limit';
-- SPFILE valueSELECT name, value, isspecifiedFROM v$spparameterWHERE name = 'pga_aggregate_limit';
-- View all PGA-related parameters togetherSELECT name, value/1024/1024 AS mb, isdefaultFROM v$parameterWHERE name IN ('pga_aggregate_target', 'pga_aggregate_limit', 'workarea_size_policy', 'memory_target')ORDER BY name;
-- Current total PGA in use vs both limitsSELECT t.value/1024/1024 AS target_mb, l.value/1024/1024 AS hard_limit_mb, u.value/1024/1024 AS total_allocated_mb, ROUND(u.value/t.value*100,1) AS pct_of_target, ROUND(u.value/l.value*100,1) AS pct_of_limitFROM v$pgastat u, v$parameter t, v$parameter lWHERE u.name = 'total PGA allocated' AND t.name = 'pga_aggregate_target' AND l.name = 'pga_aggregate_limit';Setting the Parameter
Section titled “Setting the Parameter”-- Set hard limit to 3x the aggregate target (conservative headroom)ALTER SYSTEM SET pga_aggregate_limit = 12G SCOPE=BOTH;
-- Disable the hard limit entirely (0 = no enforcement; use with caution)ALTER SYSTEM SET pga_aggregate_limit = 0 SCOPE=BOTH;
-- Typical pairing: target + limitALTER SYSTEM SET pga_aggregate_target = 4G SCOPE=BOTH;ALTER SYSTEM SET pga_aggregate_limit = 8G SCOPE=BOTH;
-- Verify the pair is consistentSELECT name, value/1024/1024 AS mbFROM v$parameterWHERE name IN ('pga_aggregate_target', 'pga_aggregate_limit')ORDER BY name;Constraint: PGA_AGGREGATE_LIMIT must be >= PGA_AGGREGATE_TARGET. Oracle will not allow a limit smaller than the target. The minimum permitted value (when non-zero) is 2GB.
Tuning Guidance
Section titled “Tuning Guidance”Recommended Values
Section titled “Recommended Values”The limit should be high enough that normal workload spikes never reach it, while still protecting against genuine runaway memory consumption.
| PGA_AGGREGATE_TARGET | Recommended PGA_AGGREGATE_LIMIT |
|---|---|
| 1GB | 2GB (minimum; use with caution) |
| 2GB | 4GB – 6GB |
| 4GB | 8GB – 12GB |
| 8GB | 16GB – 24GB |
| 16GB | 32GB – 40GB |
| 32GB | 48GB – 64GB |
General rule: Set PGA_AGGREGATE_LIMIT to 2–3x PGA_AGGREGATE_TARGET. Setting it too close to the target increases the risk of legitimate workloads triggering session kills. Setting it too high reduces its protective value.
How to Size
Section titled “How to Size”-- Check the peak PGA usage recorded since instance startupSELECT name, value/1024/1024 AS mbFROM v$pgastatWHERE name IN ( 'aggregate PGA target parameter', 'aggregate PGA auto target', 'total PGA inuse', 'total PGA allocated', 'maximum PGA allocated', 'global memory bound')ORDER BY name;
-- Find sessions currently using the most PGASELECT s.sid, s.serial#, s.username, s.status, ROUND(p.pga_alloc_mem/1024/1024, 1) AS pga_alloc_mb, ROUND(p.pga_max_mem/1024/1024, 1) AS pga_peak_mb, s.sql_id, s.moduleFROM v$session sJOIN v$process p ON p.addr = s.paddrWHERE p.pga_alloc_mem > 100*1024*1024 -- Sessions using > 100MB PGAORDER BY p.pga_alloc_mem DESCFETCH FIRST 25 ROWS ONLY;
-- Check for SQL statements with large work areas (potential limit triggers)SELECT sql_id, operation_type, ROUND(estimated_optimal_size/1024/1024, 1) AS optimal_mb, ROUND(last_memory_used/1024/1024, 1) AS last_used_mb, last_executionFROM v$sql_workareaWHERE estimated_optimal_size > 500*1024*1024 -- Work areas > 500MBORDER BY estimated_optimal_size DESCFETCH FIRST 20 ROWS ONLY;What Happens When the Limit Is Reached
Section titled “What Happens When the Limit Is Reached”When total PGA allocation hits PGA_AGGREGATE_LIMIT, Oracle takes these actions in order:
- Abort the largest PGA consumers: Oracle first attempts to abort the current SQL call (not the session) of the process with the greatest PGA usage. The session receives ORA-04036.
- Escalate to session termination: If the total PGA is still above the limit after aborting the call, Oracle terminates the session itself.
- Background process protection: Background processes (LGWR, DBWR, etc.) are never killed. If they are the top PGA consumers, the next-largest user process is targeted instead.
-- Monitor alert log for ORA-04036 occurrences-- (run from the OS or via ADRCI)-- adrci> show alert -tail 100
-- Check for recently terminated sessions (track in audit log)SELECT os_username, db_username, action_name, extended_timestamp, return_codeFROM unified_audit_trailWHERE return_code = 4036 -- ORA-04036 AND extended_timestamp > SYSTIMESTAMP - INTERVAL '1' DAYORDER BY extended_timestamp DESC;Monitoring
Section titled “Monitoring”-- Dashboard: PGA target, limit, and current usageSELECT ROUND(a.value/1024/1024, 0) AS target_mb, ROUND(b.value/1024/1024, 0) AS hard_limit_mb, ROUND(c.value/1024/1024, 0) AS current_alloc_mb, ROUND(d.value/1024/1024, 0) AS peak_alloc_mb, ROUND(c.value/b.value*100, 1) AS pct_of_limit, CASE WHEN c.value/b.value > 0.85 THEN 'WARNING: > 85% of limit' WHEN c.value/b.value > 0.70 THEN 'CAUTION: > 70% of limit' ELSE 'OK' END AS statusFROM v$parameter aCROSS JOIN v$parameter bCROSS JOIN v$pgastat cCROSS JOIN v$pgastat dWHERE a.name = 'pga_aggregate_target' AND b.name = 'pga_aggregate_limit' AND c.name = 'total PGA allocated' AND d.name = 'maximum PGA allocated';
-- Check V$PROCESS for any process currently near PGA limit thresholdSELECT COUNT(*) AS sessions_over_500mbFROM v$processWHERE pga_alloc_mem > 500*1024*1024;
-- PGA workarea efficiency (should be mostly optimal)SELECT operation_type, optimal_executions, onepass_executions, multipasses_executions, ROUND(optimal_executions / NULLIF(optimal_executions + onepass_executions + multipasses_executions, 0) * 100, 1) AS optimal_pctFROM v$sql_workarea_histogramWHERE optimal_executions + onepass_executions + multipasses_executions > 0ORDER BY operation_type;Common Issues
Section titled “Common Issues”Issue 1: Legitimate Workloads Triggering ORA-04036 Session Kills
Section titled “Issue 1: Legitimate Workloads Triggering ORA-04036 Session Kills”Large ETL jobs, bulk analytical queries, or parallel query operations may legitimately require PGA beyond the limit, causing unexpected session termination.
Resolution: Increase both PGA_AGGREGATE_TARGET and PGA_AGGREGATE_LIMIT proportionally. Identify the specific SQL causing high PGA usage and either optimize it or provide more memory.
-- Identify the top PGA-consuming SQL in the library cacheSELECT sql_id, ROUND(SUM(last_memory_used)/1024/1024, 1) AS total_last_used_mb, ROUND(SUM(estimated_optimal_size)/1024/1024, 1) AS total_optimal_mb, COUNT(*) AS workarea_countFROM v$sql_workareaGROUP BY sql_idORDER BY SUM(last_memory_used) DESCFETCH FIRST 15 ROWS ONLY;Issue 2: PGA_AGGREGATE_LIMIT Defaults to 2GB When PGA_AGGREGATE_TARGET Is Small
Section titled “Issue 2: PGA_AGGREGATE_LIMIT Defaults to 2GB When PGA_AGGREGATE_TARGET Is Small”If PGA_AGGREGATE_TARGET is set to, say, 512MB, the default PGA_AGGREGATE_LIMIT (200% of target = ~1GB, but floor of 2GB applies) may be set too close to real-world peak usage on an active system.
Resolution: Explicitly set PGA_AGGREGATE_LIMIT to a value that reflects actual peak demand observed via maximum PGA allocated in V$PGASTAT.
-- Check maximum PGA ever allocated since instance startupSELECT value/1024/1024 AS peak_pga_mbFROM v$pgastatWHERE name = 'maximum PGA allocated';
-- Set limit to peak + 50% buffer-- e.g., if peak is 3GB: ALTER SYSTEM SET pga_aggregate_limit = 5G SCOPE=BOTH;Issue 3: Disabling the Limit (Setting to 0) on Memory-Constrained Servers
Section titled “Issue 3: Disabling the Limit (Setting to 0) on Memory-Constrained Servers”Setting PGA_AGGREGATE_LIMIT = 0 removes all enforcement. On servers with limited RAM, this can allow Oracle processes to consume memory needed by the OS, leading to OOM kills of Oracle processes by the OS kernel.
Resolution: Never set PGA_AGGREGATE_LIMIT = 0 on production systems unless you have a specific, well-tested reason. Keep the limit enabled and sized generously rather than disabling it.
Related Parameters
Section titled “Related Parameters”- PGA_AGGREGATE_TARGET — The soft target that PGA_AGGREGATE_LIMIT enforces; limit must be >= target
- SGA_TARGET — SGA budget; total memory = SGA_TARGET + PGA_AGGREGATE_LIMIT must stay within available RAM
- MEMORY_TARGET — Full AMM mode; PGA_AGGREGATE_LIMIT still applies as a safety net even under AMM
- SGA_MAX_SIZE — Analogous ceiling for SGA
Related Errors
Section titled “Related Errors”- ORA-04036: PGA Memory Limit Exceeded — Direct result of hitting PGA_AGGREGATE_LIMIT; session is killed by Oracle to protect the OS
Version Notes
Section titled “Version Notes”| Version | Notes |
|---|---|
| Oracle 12c (12.1.0.1) | PGA_AGGREGATE_LIMIT introduced |
| Oracle 12c R2 | PDB-level PGA_AGGREGATE_LIMIT supported; CDB limit acts as ceiling for all PDBs |
| Oracle 18c | Default calculation (200% of PGA_AGGREGATE_TARGET, floor 2GB) unchanged |
| Oracle 19c | No functional changes; remains a best practice for production systems |
| Oracle 21c / 23ai | Behavior unchanged; continues to protect against runaway PGA consumption |