ORA-04036 fires when instance-wide PGA consumption crosses PGA_AGGREGATE_LIMIT, the hard cap introduced in 12c. This is not a tuning warning. The database is defending itself by killing or interrupting work.

PGA_AGGREGATE_TARGET is a soft target Oracle tries to honor. PGA_AGGREGATE_LIMIT is an enforced ceiling. Sessions can exceed the target legitimately. Crossing the limit triggers Oracle to abort the call of, and then terminate, the sessions holding the most untunable PGA. SYS and most background processes are not eligible for termination, which produces a distinct and more dangerous failure mode described below.

The Linux OOM killer may also be involved if SGA (hugepages) + PGA + OS needs exceed physical RAM, but ORA-04036 itself is Oracle’s internal mechanism. Both can fire in the same incident.

What this means

When aggregate PGA crosses PGA_AGGREGATE_LIMIT:

  • The CKPT background process checks PGA usage every three seconds.
  • Oracle first aborts the call of the session holding the most untunable PGA. Untunable memory is memory Oracle cannot release on demand: sort areas in use, PL/SQL collections, certain call memory.
  • If the instance is still over the limit after the abort, Oracle terminates the session.
  • SYS sessions and most background processes (DBWn, LGWR, SMON, PMON, MMON, and so on) are not terminated. Their PGA usage is written to trace files instead.

The last point is the dangerous variant. When a background process is the top PGA consumer, Oracle cannot enforce the limit against it. The alert log will say something like:

PGA_AGGREGATE_LIMIT has been exceeded but some processes using the most PGA memory are not eligible to receive ORA-4036 interrupts.

In that case ORA-04036 still fires for user sessions, but the root cause keeps growing. Killing user sessions will not self-correct the instance.

In 19c and later, the incident dump produced when ORA-04036 fires includes a “Top 10 processes” section showing private memory usage per Oracle process. Read that dump before guessing.

flowchart TD
    A[Aggregate PGA rises] --> B{Crosses PGA_AGGREGATE_LIMIT?}
    B -->|No| Z[Normal operation]
    B -->|Yes| C[CKPT detects every 3s]
    C --> D[Abort call of highest-PGA session]
    D --> E{Still over limit?}
    E -->|No| Z
    E -->|Yes| F[Terminate the session]
    F --> G{Top consumer user or background?}
    G -->|User| Z
    G -->|Background| H[Not eligible for ORA-4036
PGA written to trace] H --> I[Persistent overage
user sessions keep dying]

Common causes

CauseWhat it looks likeFirst thing to check
Unbounded PL/SQL collection or LOBOne session’s PGA_MAX_MEM grows monotonically over its lifetimeV$PROCESS.PGA_MAX_MEM per session
Massive serial sort or hash joinSingle SQL doing direct path read temp / direct path write temp, one big consumerV$SQL_WORKAREA_ACTIVE, top PGA consumers
Background PGA leak (MMON, space slaves)“Not eligible to receive ORA-4036 interrupts” in alert logIncident trace “Top 10 processes” section
Too many sessions with moderate PGAtotal PGA allocated tracks session count linearlyV$PGASTAT vs V$SESSION count
PGA_AGGREGATE_LIMIT set too low for workloadORA-04036 fires at start of batch or right after restartSHOW PARAMETER pga_aggregate_limit
OS memory pressure as a confounderdmesg OOM kills alongside ORA-04036; ORA-27300, ORA-27301dmesg, /proc/meminfo

Quick checks

All read-only. Run as DBA.

-- Show PGA configuration
SHOW PARAMETER pga_aggregate_target;
SHOW PARAMETER pga_aggregate_limit;
SHOW PARAMETER memory_target;       -- AMM check
SHOW PARAMETER sga_target;
-- Aggregate PGA state from V$PGASTAT
SELECT NAME, VALUE
FROM V$PGASTAT
WHERE NAME IN (
  'aggregate PGA target parameter',
  'total PGA inuse',
  'total PGA allocated',
  'maximum PGA allocated',
  'over allocation count',
  'total freeable PGA memory',
  'cache hit percentage'
);
-- Top PGA consumers, with OS PID and SQL_ID
SELECT p.SPID,
       p.PGA_USED_MEM/1048576  AS pga_used_mb,
       p.PGA_ALLOC_MEM/1048576 AS pga_alloc_mb,
       p.PGA_MAX_MEM/1048576   AS pga_max_mb,
       s.SID, s.USERNAME, s.SQL_ID, s.PROGRAM
FROM V$PROCESS p
LEFT JOIN V$SESSION s ON p.ADDR = s.PADDR
ORDER BY p.PGA_ALLOC_MEM DESC
FETCH FIRST 20 ROWS ONLY;
-- Per-category breakdown for top offenders (12c+)
SELECT PID, SERIAL#, NAME, CATEGORY,
       ALLOCATED/1048576 AS alloc_mb,
       USED/1048576      AS used_mb,
       MAX_ALLOCATED/1048576 AS max_mb
FROM V$PROCESS_MEMORY
ORDER BY ALLOCATED DESC
FETCH FIRST 20 ROWS ONLY;
-- Sessions currently spilling to temp (PGA undersized indicator)
SELECT EVENT, TOTAL_WAITS, TIME_WAITED_MICRO
FROM V$SYSTEM_EVENT
WHERE EVENT IN ('direct path read temp', 'direct path write temp');
# Confirm ORA-04036 in the alert log and look for ineligible-process text
adrci exec="show alert -tail 500" | grep -E "ORA-04036|ORA-4036|not eligible"

# Rule out OS OOM killer as a confounder
dmesg -T | grep -iE "out of memory|oom|killed process"

How to diagnose it

  1. Confirm ORA-04036 in the alert log. Note whether the “not eligible to receive ORA-4036 interrupts” message appears alongside it. That changes the playbook.
  2. Snapshot V$PGASTAT. Compare total PGA allocated against PGA_AGGREGATE_LIMIT and PGA_AGGREGATE_TARGET. The ratio tells you whether you are nudging the limit or blowing through it.
  3. Identify the top PGA consumer in V$PROCESS and break it down with V$PROCESS_MEMORY. The CATEGORY column separates SQL, PL/SQL, OLAP, Java, and Other. A session whose PL/SQL category is huge is leaking collections. A session whose SQL category is huge is doing a large workarea operation.
  4. If the top consumer is a background process (MMON, a space background slave, DBWn), open the incident dump in the ADR. In 19c+ the dump contains a “Top 10 processes” section. Confirm which background process is the offender.
  5. Rule out OS OOM killer. If dmesg shows Oracle PIDs being killed, the real ceiling is physical RAM, not PGA_AGGREGATE_LIMIT. The fix is to free RAM (hugepages for SGA, reduce PGA footprint, move other workloads off the host), not to raise the limit.
  6. Correlate timing. Did ORA-04036 start after a stats gather, a batch window, a datapatch run, an upgrade, or a connection pool resize? PGA leaks often surface after a code change that introduced an unbounded loop.
  7. Check direct path read temp / direct path write temp trends. If they rise in step with PGA, the workload is genuinely outgrowing PGA. If PGA rises while temp spill stays flat, suspect a leak rather than legitimate demand.

Metrics and signals to monitor

SignalWhy it mattersWarning sign
total PGA allocated / PGA_AGGREGATE_LIMITHeadroom before the hard capSustained above 80%
over allocation count in V$PGASTATPersistent over-target pressureNon-zero and growing
cache hit percentage in V$PGASTATRatio of work done in PGA vs spilled to tempBelow 80% sustained
direct path read temp / direct path write tempPGA is undersized for the workRising trend
Per-process PGA_MAX_MEMDetects slow leaks in long-lived sessionsSingle PID growing monotonically
dmesg OOM killsOS-level memory ceilingAny Oracle-related entries
Alert log: “not eligible” textBackground process is the top consumerAny occurrence

Fixes

Immediate: stop the bleeding

If a single user session is the top consumer and you can identify the offending SQL_ID or program, kill the session. Rolling back an uncommitted transaction in that session releases its PGA.

-- Disruptive: kills the target session immediately
ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;

Use this when the cause is a runaway user session, not a background process.

Short-term: raise the limit

PGA_AGGREGATE_LIMIT is dynamic and can be raised without a restart:

-- Dynamically raise the limit, both spfile and memory
ALTER SYSTEM SET pga_aggregate_limit = <new_value> SCOPE=BOTH;

Do this only if physical RAM has headroom. Raising the limit above what the host can actually hold moves the failure from ORA-04036 to the OS OOM killer, which is worse because the OOM killer does not distinguish background from foreground processes.

To disable the limit entirely as an emergency workaround, for example during a datapatch run known to spike PGA:

-- Emergency only. Removes Oracle's self-protection.
ALTER SYSTEM SET pga_aggregate_limit = 0 SCOPE=BOTH;

Setting the limit to 0 disables it. Use it only for the duration of the operation, then restore a sane value.

Medium-term: reduce demand

  • Fix the PL/SQL leak. Look for collections populated in a loop without a DELETE, session-level LOBs held across calls, or associative arrays used as caches that never age out.
  • Reduce PGA_AGGREGATE_TARGET if it has drifted higher than the workload needs. Oracle sizes per-session workareas off the target; an oversized target allows individual sessions to grab more memory before Oracle starts spilling to temp.
  • Move analytical workloads to an Active Data Guard standby (licensed) or a separate instance so a single hash join cannot starve OLTP.

Confounder: free OS memory first

If the issue is total RAM, not Oracle’s cap:

  • Verify hugepages are configured for the SGA. Without hugepages, page table overhead can consume hundreds of MB per Oracle process on large SGAs. Check /proc/meminfo for HugePages_Total, HugePages_Free, and HugePages_Rsvd.
  • Avoid MEMORY_TARGET (AMM) on Linux. It uses /dev/shm instead of hugepages and makes memory leak diagnosis harder.
  • Move monitoring agents, backup scripts, or other tenants off the Oracle host.

Background-process leak: targeted workaround

If a background process is the top consumer, raising the limit only delays the next incident. Look for known defects and underscore workarounds relevant to your version. In 19c, space background process slaves have been observed to hold “control file i/o buffer” allocations for extended periods. Reducing the slave count via the underscore parameter limits the blast radius. Engage Oracle Support before changing underscore parameters.

Prevention

  • Monitor V$PGASTAT continuously. Track total PGA allocated, over allocation count, and cache hit percentage. The leading indicator is over allocation count rising before ORA-04036 ever fires.
  • Track per-process PGA_MAX_MEM. A session whose high-water mark keeps climbing across snapshots is leaking. Catch it before it becomes the top consumer.
  • Size PGA_AGGREGATE_LIMIT with explicit headroom. Peak total PGA allocated should stay below 80% of the limit. After an 18c+ upgrade, remember that MGA (Managed Global Area) is accounted under PGA, so reported PGA usage rises. A reasonable rule of thumb is to raise the limit by (max connected processes) * 4 MB after upgrade.
  • Confirm hugepages for SGA. This frees the memory Oracle would otherwise burn on page tables.
  • Avoid MEMORY_TARGET on Linux. It conflicts with hugepages and obscures leak diagnosis.
  • Validate the 19c+ “Top 10 processes” dump works in your environment. When ORA-04036 fires, you want that dump to be there.
  • Watch for the “not eligible” alert log text. It means the fix is not “kill user sessions”. It means a background process has a leak and you need Oracle Support.
  • For datapatch and other known PGA-spiking operations, temporarily raise or disable PGA_AGGREGATE_LIMIT for the duration, then restore it.

How Netdata helps

  • Per-second PGA utilization from V$PGASTAT (total PGA inuse, total PGA allocated, over allocation count, cache hit percentage) lets you see the climb toward the limit before ORA-04036 fires, not just after.
  • Correlate PGA with TPS, active sessions, and wait events. If direct path read temp waits climb alongside total PGA allocated, the workload is outgrowing PGA. If PGA climbs while TPS is flat, suspect a leak.
  • Per-process PGA tracking surfaces a single PID whose PGA_MAX_MEM grows monotonically, the signature of a slow PL/SQL or LOB leak.
  • Linux memory pressure signals on the same timeline (OOM kills from dmesg, hugepage utilization, slab, free memory) let you distinguish Oracle’s internal cap from the host’s physical RAM ceiling.
  • Anomaly detection on over allocation count and cache hit percentage flags the leading indicators of PGA pressure even when absolute values look fine.
  • Alert log parsing for ORA-04036 and the “not eligible” text routes you straight to the background-process variant when it occurs.

For the full integration, see Oracle Database monitoring with Netdata.