When Oracle’s SGA runs on regular 4KB pages, the Linux kernel maintains a page table entry for every page the SGA touches. A 100GB SGA spans roughly 26 million 4KB pages. Every Oracle process that maps the SGA (dedicated servers, background processes, parallel slaves) carries page table structures tracking those mappings. This per-process page table overhead is invisible to Oracle’s own memory views: V$SGA, V$PGASTAT, and V$SGASTAT report the SGA as configured, not as the OS actually consumes it. You only see the overhead at the OS level in /proc/<oracle_pid>/status (the VmPTE field) or system-wide in /proc/meminfo (PageTables).
The practical consequence: a “100GB SGA” costs more than 100GB of physical RAM. On a system with hundreds of connected sessions, the combined page table footprint across all Oracle processes can reach several gigabytes. That is memory the database cannot use for buffer cache, PGA, or anything productive. It is pure kernel accounting overhead that silently shrinks the effective memory available for useful work.
The root cause is almost always one of three things: HugePages were never configured at the OS level, AMM (MEMORY_TARGET) is enabled and routes the SGA through /dev/shm (which bypasses HugePages entirely), or the database was started before HugePages were allocated and silently fell back to 4KB pages. The last case is the sneakiest: HugePages can be configured later, but the running instance will not pick them up until it is bounced.
What this means
Oracle on Linux uses 2MB HugePages by default. Each HugePage covers 512 regular 4KB pages. When the SGA is backed by HugePages, the kernel tracks the mapping with a single page table entry per 2MB chunk instead of per 4KB chunk. For a 100GB SGA, that reduces the entry count from roughly 26 million to roughly 50,000 per process. Per-process page table overhead drops from potentially hundreds of megabytes to a negligible amount.
Without HugePages, this overhead compounds with connection count. A system with 500 dedicated server processes, each carrying page table entries for a large shared SGA, can burn multiple gigabytes of RAM on page tables alone. That is RAM you paid for, RAM Oracle cannot see or report in any V$ view, and RAM that pushes the system toward the OOM killer.
The Linux OOM killer does not understand Oracle’s memory model. It sees large processes consuming lots of memory and kills them. When SGA page tables plus PGA plus OS needs exceed physical RAM, the OOM killer targets Oracle server processes. Sessions vanish without explanation. If a critical background process is killed, the instance may crash.
flowchart TD
A[SGA on 4KB pages] --> B[Millions of PTEs per process]
B --> C[VmPTE: hundreds of MB per process]
C --> D[System PageTables: multiple GB]
D --> E[Invisible to V$SGA and V$PGASTAT]
E --> F[Effective free RAM shrinks]
F --> G[OOM killer targets Oracle PIDs]Common causes
| Cause | What it looks like | First thing to check |
|---|---|---|
| HugePages never configured | /proc/meminfo shows HugePages_Total = 0; PageTables is multiple GB | grep -i huge /proc/meminfo |
AMM enabled (MEMORY_TARGET set) | SGA allocated via /dev/shm; HugePages configured but unused by Oracle | SELECT VALUE FROM V$PARAMETER WHERE NAME IN ('memory_target','memory_max_target') |
| Database started before HugePages allocated | HugePages_Free equals HugePages_Total (reserved but not consumed by Oracle) | grep huge /proc/<pmon_pid>/numa_maps |
| Insufficient HugePages count | SGA partially on HugePages, partially on 4KB pages; alert log mentions mixed allocation | Compare SGA_TARGET to HugePages_Total times Hugepagesize |
Quick checks
All of these are read-only and safe to run on a production system.
# Check OS-level HugePages configuration
grep -i huge /proc/meminfo
# Check system-wide page table memory consumption
grep PageTables /proc/meminfo
# Find the pmon PID for your instance, then check its page table size
PMON_PID=$(pgrep -f "ora_pmon_${ORACLE_SID}" | head -1)
grep -E "Vm(PTE|Size)" /proc/${PMON_PID}/status
# Verify whether this instance is actually using HugePages.
# A non-zero "huge" count means the instance uses HugePages.
grep huge /proc/${PMON_PID}/numa_maps
# Check if AMM is creating shared memory files in /dev/shm
ls -lh /dev/shm/ | grep -i oracle
-- Check USE_LARGE_PAGES setting (should not be FALSE)
SELECT NAME, VALUE FROM V$PARAMETER WHERE NAME = 'use_large_pages';
-- Check memory management mode (MEMORY_TARGET must be unset for HugePages)
SELECT NAME, VALUE FROM V$PARAMETER
WHERE NAME IN ('memory_target', 'memory_max_target', 'sga_target', 'sga_max_size');
-- Check actual SGA size
SELECT NAME, VALUE/1024/1024/1024 AS gb FROM V$SGA;
How to diagnose it
Confirm HugePages are configured at the OS level. Run
grep -i huge /proc/meminfo. IfHugePages_Totalis 0, HugePages were never configured. IfHugePages_Totalis non-zero butHugePages_FreeequalsHugePages_Total, the pages are reserved but not consumed by any process.Verify the database is actually using them. Find the pmon PID for the instance and check
/proc/<pmon_pid>/numa_maps. If there are no lines containing “huge” with a non-zero count, the instance is running entirely on 4KB pages. This is the definitive check.Rule out AMM. Query
V$PARAMETERformemory_targetandmemory_max_target. If either is non-zero, the database is using Automatic Memory Management, which allocates the SGA through POSIX shared memory files in/dev/shm. This mechanism is fundamentally incompatible with HugePages. You will see files under/dev/shmowned by the oracle user.Check the alert log for HugePages-related messages. When
USE_LARGE_PAGESis set toONLYand insufficient HugePages exist, the database fails to start. When set toTRUE(the non-Exadata default) and HugePages are insufficient or absent, the database starts on regular pages and logs a recommendation. Search the alert log for “HugePages” entries.Measure the actual page table overhead. Pick a representative dedicated server process (not just pmon). Run
grep VmPTE /proc/<oracle_pid>/status. The reported value is in KB. Multiply it by your typical connection count to estimate the aggregate overhead. Compare to/proc/meminfoPageTablesfor the system-wide figure.Check for OOM killer activity. Run
dmesg | grep -i "out of memory\|oom"and check/var/log/messages. If the OOM killer has targeted Oracle PIDs, page table overhead may be contributing to memory pressure alongside SGA and PGA.
Metrics and signals to monitor
| Signal | Why it matters | Warning sign |
|---|---|---|
/proc/meminfo PageTables | System-wide page table memory. Directly reflects 4KB page overhead for large SGAs. | Multiple GB on a system with a large SGA and no HugePages |
/proc/meminfo HugePages_Total and HugePages_Free | Confirms HugePages are configured and consumed. Free = Total means Oracle is not using them. | HugePages_Total = 0 or HugePages_Free = HugePages_Total |
Per-process VmPTE from /proc/<pid>/status | Page table size per Oracle process. Scales with SGA size when not using HugePages. | Hundreds of MB per process |
V$PARAMETER memory_target | If non-zero, AMM is active and HugePages cannot be used. | Any non-zero value |
V$PARAMETER use_large_pages | Controls whether Oracle attempts to use HugePages. FALSE means never. | FALSE |
| System memory utilization vs physical RAM | SGA + PGA + page tables + OS needs must fit in physical RAM. | Sustained above 90% with Oracle processes as top consumers |
dmesg OOM killer entries | OOM killer targeting Oracle PIDs indicates memory exhaustion, often exacerbated by page table overhead. | Any Out of memory: Kill process referencing Oracle PIDs |
Fixes
If AMM is enabled: switch to ASMM
AMM (MEMORY_TARGET / MEMORY_MAX_TARGET) manages SGA and PGA together through /dev/shm memory-mapped files. This is incompatible with HugePages. Oracle documentation explicitly states that AMM is not recommended on Linux for this reason.
To switch to ASMM (Automatic Shared Memory Management), which uses System V shared memory and is compatible with HugePages:
-- Requires a database restart to take effect
ALTER SYSTEM SET memory_target = 0 SCOPE = SPFILE;
ALTER SYSTEM SET memory_max_target = 0 SCOPE = SPFILE;
ALTER SYSTEM SET sga_target = <desired_sga_size> SCOPE = SPFILE;
ALTER SYSTEM SET pga_aggregate_target = <desired_pga_size> SCOPE = SPFILE;
This is disruptive: the database must be bounced.
Allocate HugePages at the OS level
Calculate the number of HugePages needed. Oracle provides the hugepages_settings.sh script (MOS Doc ID 401749.1) for this purpose. Prerequisites: all databases must be running, and AMM must be disabled. Running the script with AMM enabled or with databases stopped produces incorrect values.
A rough manual calculation: nr_hugepages = ceil(SGA_SIZE_BYTES / Hugepagesize). Leave a small buffer. Oracle recommends reserving no more than 70% of total RAM for HugePages, keeping at least 30% available for regular pages used by PGA and the OS.
# Set at runtime (may fail if memory is fragmented; reboot is more reliable)
sysctl -w vm.nr_hugepages=<calculated_value>
# Make persistent across reboots
echo "vm.nr_hugepages = <calculated_value>" >> /etc/sysctl.d/99-oracle-hugepages.conf
Setting vm.nr_hugepages at runtime may fail if the kernel cannot find enough contiguous memory. A reboot guarantees allocation.
Set memlock limits
The oracle OS user needs permission to lock HugePages in memory. Set the memlock limit in /etc/security/limits.conf (or the equivalent in your PAM configuration) to at least the size of the HugePages pool in KB.
oracle soft memlock <value_in_kb>
oracle hard memlock <value_in_kb>
The minimum value is the SGA size (or the total HugePages allocation) in KB. A common approach is to set memlock to at least 90% of total physical RAM in KB, which leaves headroom for future SGA growth. Verify the limit takes effect by logging in as the oracle user and running ulimit -l.
Configure USE_LARGE_PAGES
Set USE_LARGE_PAGES to control Oracle’s HugePages behavior:
| Value | Behavior |
|---|---|
TRUE (non-Exadata default) | Uses HugePages if available. Falls back to 4KB pages if insufficient. |
ONLY | Uses only HugePages. Fails to start if insufficient. |
AUTO (19c+) | Configures the correct number of HugePages at startup, then uses them. Falls back to mixed allocation if the OS cannot provide enough. |
AUTO_ONLY (19c+, Exadata default) | Configures HugePages at startup. Fails to start if it cannot allocate enough. |
FALSE | Never uses HugePages. Do not use this in production. |
ALTER SYSTEM SET use_large_pages = ONLY SCOPE = SPFILE;
ONLY is the safest choice for catching misconfiguration early: the database refuses to start without HugePages rather than silently degrading.
Handle Transparent HugePages
Transparent HugePages (THP) is a separate kernel feature from explicit HugePages. Oracle’s guidance differs by version:
- For releases prior to 23ai: Oracle recommends disabling THP entirely (
echo never > /sys/kernel/mm/transparent_hugepage/enabled). - For 23ai and later on UEK7 kernels: Oracle recommends setting THP to
madviseinstead of fully disabling it.
On RHEL7/OL7 and later, the tuned profile may re-enable THP after boot even if grub is configured. Create a custom tuned profile that sets the THP value persistently.
Oracle does not recommend using 1GB HugePages for database workloads (MOS Doc ID 1607545.1). The default 2MB page size is the supported configuration.
Bounce the database to activate HugePages
A running instance will not switch to HugePages dynamically. Even if you allocate HugePages at the OS level while the database is running, the SGA remains on 4KB pages until the instance restarts. This is the single most common cause of “HugePages configured but not used.”
After configuring HugePages, memlock, and USE_LARGE_PAGES, schedule a maintenance window and restart the database. After restart, re-run the numa_maps check on the pmon process to confirm HugePages are in use.
RAC: account for GIMR
On RAC clusters, the Grid Infrastructure Management Repository (GIMR) consumes HugePages before database instances start. If the total HugePages pool is insufficient to cover GIMR plus all database SGAs, database instances may silently fall back to regular pages. Size the HugePages pool to cover GIMR requirements (up to approximately 1GB) plus all database SGAs.
Prevention
Bake HugePages configuration into provisioning templates. The
vm.nr_hugepagessysctl, memlock limits, THP settings, andUSE_LARGE_PAGESshould all be part of your AMI, kickstart, or Terraform configuration for Oracle hosts. Do not leave HugePages as a post-install manual step.Use
USE_LARGE_PAGES = ONLYorAUTO_ONLY. These values make misconfiguration fail loudly at startup instead of silently degrading. A database that refuses to start because HugePages are insufficient is a better outcome than a database that starts on 4KB pages and slowly drives the system toward OOM.Verify after every bounce. After any database restart, check
/proc/<pmon_pid>/numa_mapsfor “huge” entries. This catches cases where HugePages were accidentally reduced or AMM was inadvertently enabled.Monitor HugePages utilization. Track
HugePages_Total,HugePages_Free, and system-widePageTablesfrom/proc/meminfo. A sudden increase inPageTablesorHugePages_Freeafter a restart indicates the instance fell back to 4KB pages.Avoid AMM on Linux. Use ASMM (
SGA_TARGET+PGA_AGGREGATE_TARGET) instead. This is an explicit Oracle recommendation for Linux deployments.
How Netdata helps
OS-level memory visibility that Oracle views lack. Netdata collects
/proc/meminfoat per-second granularity, includingPageTables,HugePages_Total, andHugePages_Free. This exposes the page table overhead thatV$SGAandV$PGASTATcannot see.Correlation between connection count and page table growth. When page table memory scales with session count, Netdata’s per-second charts let you see the relationship between connection spikes and
PageTablesgrowth in the same time window.HugePages consumption tracking. A drop in
HugePages_Freeto zero (orHugePages_Totalgoing to zero after a reboot) signals that the instance lost its HugePages backing. Without monitoring, this is discovered only when OOM kills start.OOM killer detection. Netdata surfaces kernel OOM events. Correlating these with memory utilization charts and Oracle process counts pinpoints whether page table overhead contributed to the kill.
Memory pressure before it bites. Tracking
MemAvailablealongside SGA and PGA trends gives early warning when effective free RAM is shrinking due to invisible page table consumption.
Netdata’s Oracle Database monitoring with Netdata brings these signals together with per-second metrics and ML anomaly detection.
Related guides
- How Oracle Database actually works in production: a mental model for operators
- Oracle archive log destination full: V$ARCHIVE_DEST_STATUS, the ERROR state, and space
- Oracle autoextend hit MAXSIZE: the space gotcha with a half-empty filesystem
- Oracle blocking sessions: finding the blocker at the head of the chain
- Oracle ‘buffer busy waits’: hot blocks, sequence headers, and index leaf splits
- Oracle ‘Thread N cannot allocate new log’: the archive hang that masquerades as up
- Oracle ‘Checkpoint not complete’: redo log sizing, DBWn, and log-switch stalls
- Oracle ‘cursor: pin S wait on X’: mutex contention on hot cursors
- Oracle ‘db file scattered read’: multiblock reads, full scans, and plan regressions
- Oracle ‘db file sequential read’: single-block index reads and buffer cache misses
- Oracle ’enq: TM - contention’: unindexed foreign keys and table-level locks
- Oracle ’enq: TX - row lock contention’: blocking sessions and uncommitted DML






