Standard Linux memory pages are 4 KB, and the kernel must maintain a Translation Lookaside Buffer (TLB) entry for each mapped page. Database systems that manage large shared memory segments — such as PostgreSQL’s shared_buffers, Oracle’s SGA, or MySQL’s InnoDB buffer pool — can create millions of TLB entries, causing frequent TLB misses that significantly increase memory access latency. Linux Huge Pages reduce this overhead by using 2 MB pages instead of 4 KB, cutting the number of TLB entries needed by a factor of 512. On RHEL 9, configuring both static Huge Pages and controlling Transparent Huge Pages (THP) is a high-impact, low-risk optimization for any database workload.

Prerequisites

  • RHEL 9 system with root or sudo access
  • A database server (PostgreSQL, Oracle, or MySQL/MariaDB) installed and configured
  • Sufficient physical RAM to allocate huge pages without exhausting memory
  • Basic familiarity with Linux memory management concepts

Step 1 — Checking Current Huge Page Status

Before making any changes, examine the current state of huge page allocation in /proc/meminfo. The key fields are HugePages_Total (allocated), HugePages_Free (available), HugePages_Rsvd (reserved by processes), and Hugepagesize (always 2048 kB on x86_64).

cat /proc/meminfo | grep -i huge

# Also check the current Transparent Huge Pages setting
cat /sys/kernel/mm/transparent_hugepage/enabled

# Check total system RAM to plan allocation
free -h
grep MemTotal /proc/meminfo

By default, RHEL 9 has Transparent Huge Pages enabled in madvise mode, and static huge pages are set to zero.

Step 2 — Calculating the Required Number of Huge Pages

Calculate how many 2 MB huge pages are needed to cover your database shared memory. For PostgreSQL, this is driven by shared_buffers. For Oracle, it is the SGA size. Add 10–15% overhead for other shared memory segments.

# Formula: nr_hugepages = CEIL( (shared_memory_in_bytes * 1.1) / 2097152 )
# Example: 8 GB shared_buffers = 8589934592 bytes
# nr_hugepages = CEIL(8589934592 * 1.1 / 2097152) = CEIL(4505.6) = 4506

# Quick calculation with Python
python3 -c "
import math
shared_bytes = 8 * 1024**3   # 8 GB
overhead     = 1.10           # 10% overhead
page_size    = 2 * 1024**2    # 2 MB
pages = math.ceil(shared_bytes * overhead / page_size)
print(f'Recommended vm.nr_hugepages = {pages}')
"

Step 3 — Configuring Static Huge Pages in sysctl.conf

Set the huge page count in /etc/sysctl.conf and also configure the supplementary group that is permitted to use huge pages. The database process must belong to this group. For PostgreSQL, the relevant group is postgres.

# Get the GID of the postgres user's primary group
id postgres

# Add huge page settings to sysctl.conf (replace GID with actual value)
sudo tee -a /etc/sysctl.conf <<'EOF'

# Huge Pages for database performance
vm.nr_hugepages = 512
vm.hugetlb_shm_group = 26
EOF

# Apply immediately without reboot
sudo sysctl -p

# Verify allocation (HugePages_Total should now equal 512)
grep HugePages /proc/meminfo

If HugePages_Total is less than the requested value, the system could not allocate contiguous 2 MB regions. Allocate huge pages earlier in the boot process before memory becomes fragmented, or add the setting to GRUB (hugepages=512) for boot-time allocation.

Step 4 — Disabling Transparent Huge Pages for Databases

Transparent Huge Pages (THP) automatically promotes standard pages to 2 MB pages at runtime. While beneficial for some workloads, THP causes latency spikes in databases because the khugepaged daemon periodically stalls processes during page promotion and the compaction required for defragmentation. All major database vendors (PostgreSQL, Oracle, MongoDB, Redis) recommend disabling THP.

# Disable THP immediately (takes effect now, lost on reboot)
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag

# Persist via a systemd unit (recommended over rc.local on RHEL 9)
sudo tee /etc/systemd/system/disable-thp.service < /sys/kernel/mm/transparent_hugepage/enabled && echo never > /sys/kernel/mm/transparent_hugepage/defrag"
RemainAfterExit=yes

[Install]
WantedBy=basic.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now disable-thp.service
sudo systemctl status disable-thp.service

Step 5 — Configuring PostgreSQL to Use Huge Pages

PostgreSQL will use huge pages automatically if they are available and the huge_pages parameter is set to on. With on, PostgreSQL will fail to start if huge pages cannot be allocated, ensuring the configuration is intentional. Use try to fall back silently.

# Find the postgresql.conf file
sudo -u postgres psql -c "SHOW config_file;"

# Edit postgresql.conf — set these parameters
sudo tee -a /var/lib/pgsql/data/postgresql.conf <<'EOF'

# Huge Pages configuration
huge_pages = on
shared_buffers = 8GB
EOF

# Restart PostgreSQL to apply
sudo systemctl restart postgresql

# Verify PostgreSQL is using huge pages (HugePages_Rsvd should increase)
grep HugePages /proc/meminfo

Step 6 — Verifying the Configuration

After restarting the database, confirm that huge pages are actually in use. HugePages_Rsvd shows how many pages are reserved by running processes, and HugePages_Free minus HugePages_Rsvd gives unallocated pages.

# Check allocation status
grep -E "HugePages_Total|HugePages_Free|HugePages_Rsvd|HugePages_Surp" /proc/meminfo

# Confirm PostgreSQL process is using huge pages via /proc
PG_PID=$(pgrep -ox postgres)
grep -i huge /proc/$PG_PID/smaps | head -20

# Confirm THP is still disabled after reboot
cat /sys/kernel/mm/transparent_hugepage/enabled

Conclusion

You have configured static Huge Pages and disabled Transparent Huge Pages on RHEL 9, then configured PostgreSQL to take advantage of the larger page sizes. This reduces TLB pressure for large shared memory workloads, resulting in measurable reductions in memory access latency for database-intensive applications. The systemd unit ensures THP stays disabled across reboots in a clean, maintainable way that is consistent with RHEL 9’s service management conventions.

Next steps: How to Tune Linux Kernel Parameters with sysctl on RHEL 9, How to Monitor PostgreSQL Performance with pg_stat_statements on RHEL 9, and How to Configure NUMA-Aware Memory Allocation for Databases on RHEL 9.