Configure Linux transparent huge pages and memory optimization for database workloads

Advanced 25 min Apr 17, 2026 914 views
Ubuntu 24.04 Ubuntu 22.04 Debian 12 AlmaLinux 9 Rocky Linux 9 Fedora 41

Learn to configure transparent huge pages (THP) and optimize Linux memory management for database workloads. Covers THP disable/enable strategies, performance monitoring, and automation with systemd.

Prerequisites

  • Root or sudo access
  • Basic understanding of Linux memory management
  • Database workload running on the system

What this solves

Transparent Huge Pages (THP) can significantly impact database performance, causing memory fragmentation and unpredictable latency spikes. This tutorial shows you how to configure THP settings, optimize memory allocation for database workloads, and implement monitoring to track performance impact across different database systems.

Understanding transparent huge pages

Check current THP status

First, examine your system's current transparent huge pages configuration to understand the baseline.

cat /sys/kernel/mm/transparent_hugepage/enabled
cat /sys/kernel/mm/transparent_hugepage/defrag
grep -i hugepages /proc/meminfo

Monitor THP allocation statistics

View detailed statistics about huge page allocation and fragmentation events.

cat /proc/vmstat | grep -E "thp_|hugepages"
cat /sys/kernel/mm/transparent_hugepage/khugepaged/pages_collapsed
cat /sys/kernel/mm/transparent_hugepage/khugepaged/full_scans

Step-by-step THP configuration

Create THP management script

Create a comprehensive script to manage transparent huge pages settings dynamically.

sudo mkdir -p /usr/local/bin
sudo tee /usr/local/bin/thp-manager.sh
#!/bin/bash

# THP Manager Script for Database Workloads
# Usage: thp-manager.sh [disable|enable|madvise|status]

THP_ENABLED="/sys/kernel/mm/transparent_hugepage/enabled"
THP_DEFRAG="/sys/kernel/mm/transparent_hugepage/defrag"
THP_KHUGEPAGED="/sys/kernel/mm/transparent_hugepage/khugepaged"

set_thp_status() {
    local mode=$1
    case $mode in
        "disable")
            echo "never" > $THP_ENABLED
            echo "never" > $THP_DEFRAG
            echo "THP disabled completely"
            ;;
        "enable")
            echo "always" > $THP_ENABLED
            echo "always" > $THP_DEFRAG
            echo "THP enabled with aggressive allocation"
            ;;
        "madvise")
            echo "madvise" > $THP_ENABLED
            echo "madvise" > $THP_DEFRAG
            echo "THP set to application-controlled mode"
            ;;
    esac
}

show_status() {
    echo "=== Transparent Huge Pages Status ==="
    echo "Enabled: $(cat $THP_ENABLED)"
    echo "Defrag: $(cat $THP_DEFRAG)"
    echo "khugepaged scan pages: $(cat $THP_KHUGEPAGED/pages_to_scan)"
    echo "khugepaged scan sleep: $(cat $THP_KHUGEPAGED/scan_sleep_millisecs)ms"
    echo
    echo "=== Memory Statistics ==="
    grep -E "HugePages_|AnonHugePages" /proc/meminfo
    echo
    echo "=== THP Events ==="
    grep -E "thp_" /proc/vmstat | head -10
}

optimize_khugepaged() {
    # Optimize khugepaged for database workloads
    echo 4096 > $THP_KHUGEPAGED/pages_to_scan
    echo 1000 > $THP_KHUGEPAGED/scan_sleep_millisecs
    echo 32 > $THP_KHUGEPAGED/alloc_sleep_millisecs
    echo "khugepaged optimized for database workloads"
}

case "$1" in
    disable)
        set_thp_status "disable"
        ;;
    enable)
        set_thp_status "enable"
        optimize_khugepaged
        ;;
    madvise)
        set_thp_status "madvise"
        optimize_khugepaged
        ;;
    status)
        show_status
        ;;
    *)
        echo "Usage: $0 {disable|enable|madvise|status}"
        echo "  disable  - Completely disable THP (recommended for most databases)"
        echo "  enable   - Enable THP with aggressive allocation"
        echo "  madvise  - Enable THP only when requested by applications"
        echo "  status   - Show current THP configuration and statistics"
        exit 1
        ;;
esac
sudo chmod +x /usr/local/bin/thp-manager.sh

Configure THP for database workloads

Most database systems perform better with THP disabled due to memory fragmentation issues.

# Check current status
sudo /usr/local/bin/thp-manager.sh status

# Disable THP for database workloads (recommended)
sudo /usr/local/bin/thp-manager.sh disable

# Verify the change
sudo /usr/local/bin/thp-manager.sh status

Create persistent THP configuration

Make THP settings persistent across reboots using kernel parameters and systemd service.

# Update GRUB configuration
sudo tee -a /etc/default/grub.d/thp.cfg
# Disable Transparent Huge Pages for database workloads
GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT transparent_hugepage=never"
sudo update-grub
# Update GRUB configuration
sudo tee -a /etc/default/grub.d/thp.cfg
# Disable Transparent Huge Pages for database workloads
GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT transparent_hugepage=never"
sudo grub2-mkconfig -o /boot/grub2/grub.cfg

Create systemd service for THP management

Create a systemd service to apply THP settings early in the boot process as a backup to kernel parameters.

sudo tee /etc/systemd/system/thp-config.service
[Unit]
Description=Configure Transparent Huge Pages for Database Workloads
DefaultDependencies=no
After=sysinit.target local-fs.target
Before=basic.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/thp-manager.sh disable
TimeoutSec=30
RemainAfterExit=yes

[Install]
WantedBy=basic.target
sudo systemctl enable thp-config.service
sudo systemctl daemon-reload

Database-specific optimization strategies

Configure memory allocation for PostgreSQL

Optimize PostgreSQL memory settings when THP is disabled to prevent performance degradation.

sudo tee /etc/sysctl.d/99-postgresql-memory.conf
# PostgreSQL memory optimization with THP disabled

# Reduce memory fragmentation
vm.swappiness = 10

# Optimize dirty page handling
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
vm.dirty_expire_centisecs = 3000
vm.dirty_writeback_centisecs = 500

# Memory allocation optimization
vm.overcommit_memory = 2
vm.overcommit_ratio = 80

# Shared memory settings
kernel.shmmax = 17179869184
kernel.shmall = 4194304
kernel.shmmni = 4096
sudo sysctl --load=/etc/sysctl.d/99-postgresql-memory.conf

Configure memory settings for Redis

Redis requires specific memory optimizations when running without THP support.

sudo tee /etc/sysctl.d/99-redis-memory.conf
# Redis memory optimization with THP disabled

# Enable memory overcommit (required for Redis background saves)
vm.overcommit_memory = 1

# Optimize for Redis memory patterns
vm.swappiness = 1
vm.vfs_cache_pressure = 50

# Network buffer optimization for Redis replication
net.core.somaxconn = 65535
net.core.tcp_max_syn_backlog = 65535
sudo sysctl --load=/etc/sysctl.d/99-redis-memory.conf

Configure MongoDB memory optimization

MongoDB has specific requirements when THP is disabled to maintain performance.

sudo tee /etc/sysctl.d/99-mongodb-memory.conf
# MongoDB memory optimization with THP disabled

# Optimize for MongoDB's memory access patterns
vm.swappiness = 1
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5

# Reduce zone reclaim for NUMA systems
vm.zone_reclaim_mode = 0

# Network optimization for MongoDB clusters
net.core.somaxconn = 4096
net.ipv4.tcp_keepalive_time = 300
sudo sysctl --load=/etc/sysctl.d/99-mongodb-memory.conf

Monitoring THP performance impact

Create THP monitoring script

Implement comprehensive monitoring to track THP impact on database performance.

sudo tee /usr/local/bin/thp-monitor.sh
#!/bin/bash

# THP Performance Monitor
# Collects THP statistics and memory fragmentation metrics

TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
LOGFILE="/var/log/thp-monitor.log"

log_metrics() {
    echo "=== THP Metrics - $TIMESTAMP ===" >> $LOGFILE
    
    # Basic THP status
    echo "THP_ENABLED: $(cat /sys/kernel/mm/transparent_hugepage/enabled)" >> $LOGFILE
    echo "THP_DEFRAG: $(cat /sys/kernel/mm/transparent_hugepage/defrag)" >> $LOGFILE
    
    # Memory statistics
    grep -E "AnonHugePages|HugePages_" /proc/meminfo >> $LOGFILE
    
    # THP allocation statistics
    grep -E "thp_fault_alloc|thp_fault_fallback|thp_collapse_alloc" /proc/vmstat >> $LOGFILE
    
    # Memory fragmentation
    echo "FRAGMENTATION_INDEX:" >> $LOGFILE
    cat /sys/kernel/debug/extfrag/extfrag_index 2>/dev/null | head -5 >> $LOGFILE
    
    # Buddy allocator info
    echo "BUDDY_INFO:" >> $LOGFILE
    cat /proc/buddyinfo >> $LOGFILE
    
    echo "" >> $LOGFILE
}

generate_report() {
    echo "=== THP Performance Report - $TIMESTAMP ==="
    
    # Calculate THP efficiency
    FAULT_ALLOC=$(grep thp_fault_alloc /proc/vmstat | awk '{print $2}')
    FAULT_FALLBACK=$(grep thp_fault_fallback /proc/vmstat | awk '{print $2}')
    
    if [ "$FAULT_ALLOC" -gt 0 ] && [ "$FAULT_FALLBACK" -gt 0 ]; then
        TOTAL_ATTEMPTS=$((FAULT_ALLOC + FAULT_FALLBACK))
        SUCCESS_RATE=$((FAULT_ALLOC * 100 / TOTAL_ATTEMPTS))
        echo "THP Success Rate: $SUCCESS_RATE%"
    fi
    
    # Memory pressure indicators
    DIRECT_RECLAIM=$(grep pgsteal_direct /proc/vmstat | awk '{print $2}')
    KSWAPD_RECLAIM=$(grep pgsteal_kswapd /proc/vmstat | awk '{print $2}')
    echo "Direct Reclaim Events: $DIRECT_RECLAIM"
    echo "kswapd Reclaim Events: $KSWAPD_RECLAIM"
    
    # Current memory usage
    echo ""
    echo "Current Memory Usage:"
    free -h
    
    echo ""
    echo "Memory Fragmentation (lower is better):"
    awk '/Node 0/ && /DMA32|Normal/ {print $1 " " $2 ": " $NF}' /proc/buddyinfo 2>/dev/null || echo "Fragmentation data not available"
}

case "$1" in
    log)
        log_metrics
        ;;
    report)
        generate_report
        ;;
    watch)
        watch -n 5 "$0 report"
        ;;
    *)
        echo "Usage: $0 {log|report|watch}"
        echo "  log    - Log current metrics to $LOGFILE"
        echo "  report - Generate performance report"
        echo "  watch  - Continuously monitor (5-second intervals)"
        exit 1
        ;;
esac
sudo chmod +x /usr/local/bin/thp-monitor.sh
sudo touch /var/log/thp-monitor.log

Set up automated THP monitoring

Configure systemd timer to regularly collect THP performance metrics.

sudo tee /etc/systemd/system/thp-monitor.service
[Unit]
Description=THP Performance Monitoring
After=multi-user.target

[Service]
Type=oneshot
User=root
ExecStart=/usr/local/bin/thp-monitor.sh log
StandardOutput=journal
StandardError=journal
sudo tee /etc/systemd/system/thp-monitor.timer
[Unit]
Description=THP Performance Monitoring Timer
Requires=thp-monitor.service

[Timer]
OnBootSec=5min
OnUnitActiveSec=10min
Persistent=true

[Install]
WantedBy=timers.target
sudo systemctl enable thp-monitor.timer
sudo systemctl start thp-monitor.timer
sudo systemctl daemon-reload

Configure logrotate for THP monitoring

Prevent THP monitoring logs from consuming excessive disk space.

sudo tee /etc/logrotate.d/thp-monitor
/var/log/thp-monitor.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 644 root root
    postrotate
        systemctl reload rsyslog > /dev/null 2>&1 || true
    endscript
}

Advanced memory optimization techniques

Configure NUMA memory policy

On NUMA systems, configure memory policies to optimize database performance with disabled THP.

# Check NUMA topology
numactl --hardware

# Configure NUMA-aware memory allocation
sudo tee /etc/sysctl.d/99-numa-memory.conf
# NUMA memory optimization for databases

# Disable zone reclaim to prevent remote memory access penalties
vm.zone_reclaim_mode = 0

# Optimize NUMA balancing for database workloads
kernel.numa_balancing = 0

# Memory allocation preferences
vm.numa_zonelist_order = Node
sudo sysctl --load=/etc/sysctl.d/99-numa-memory.conf

Implement memory pressure monitoring

Set up monitoring for memory pressure indicators that can impact database performance.

sudo tee /usr/local/bin/memory-pressure-check.sh
#!/bin/bash

# Memory Pressure Monitoring for Database Systems

WARN_THRESHOLD=80
CRIT_THRESHOLD=95

check_memory_pressure() {
    # Get memory usage percentage
    MEMORY_USAGE=$(free | awk 'NR==2{printf "%.0f", $3*100/$2}')
    
    # Check swap usage
    SWAP_USAGE=$(free | awk 'NR==3{if($2>0) printf "%.0f", $3*100/$2; else print "0"}')
    
    # Get memory pressure stall information (if available)
    if [ -f /proc/pressure/memory ]; then
        PRESSURE_AVG10=$(awk '/some/ {print $2}' /proc/pressure/memory | cut -d'=' -f2)
        PRESSURE_TOTAL=$(awk '/some/ {print $4}' /proc/pressure/memory | cut -d'=' -f2)
    fi
    
    # Check for memory fragmentation
    FRAGMENTATION=$(awk '/Node 0.*Normal/ {print $(NF-1)}' /proc/buddyinfo 2>/dev/null | head -1)
    
    echo "Memory Usage: ${MEMORY_USAGE}%"
    echo "Swap Usage: ${SWAP_USAGE}%"
    
    if [ ! -z "$PRESSURE_AVG10" ]; then
        echo "Memory Pressure (10s avg): ${PRESSURE_AVG10}%"
    fi
    
    # Alert conditions
    if [ "$MEMORY_USAGE" -ge "$CRIT_THRESHOLD" ]; then
        echo "CRITICAL: Memory usage above ${CRIT_THRESHOLD}%"
        logger "CRITICAL: High memory usage detected: ${MEMORY_USAGE}%"
    elif [ "$MEMORY_USAGE" -ge "$WARN_THRESHOLD" ]; then
        echo "WARNING: Memory usage above ${WARN_THRESHOLD}%"
        logger "WARNING: Memory usage elevated: ${MEMORY_USAGE}%"
    fi
    
    if [ "$SWAP_USAGE" -gt "10" ]; then
        echo "WARNING: Swap usage detected: ${SWAP_USAGE}%"
        logger "WARNING: System using swap memory: ${SWAP_USAGE}%"
    fi
}

check_memory_pressure
sudo chmod +x /usr/local/bin/memory-pressure-check.sh

Verify your setup

Verify THP configuration

Confirm that transparent huge pages are properly configured for your database workload.

# Check THP status
sudo /usr/local/bin/thp-manager.sh status

# Verify kernel parameters will persist after reboot
grep transparent_hugepage /proc/cmdline

# Check systemd service status
sudo systemctl status thp-config.service

Monitor performance impact

Generate a performance report and verify monitoring is working correctly.

# Generate current performance report
sudo /usr/local/bin/thp-monitor.sh report

# Check monitoring timer status
sudo systemctl status thp-monitor.timer

# View recent monitoring data
sudo tail -20 /var/log/thp-monitor.log

# Test memory pressure monitoring
sudo /usr/local/bin/memory-pressure-check.sh

Test database performance

Run basic performance tests to verify the THP configuration benefits your database workload. This setup improves database performance by reducing memory fragmentation and eliminating THP-related latency spikes that can impact query response times.

# Check system memory allocation efficiency
grep -E "thp_fault_fallback|thp_fault_alloc" /proc/vmstat

# Monitor memory fragmentation
cat /proc/buddyinfo | awk '{print $1, $2, $NF}'

# Check for memory reclaim events (should be minimal)
grep -E "pgsteal_|pgscan_" /proc/vmstat

Common issues

SymptomCauseFix
THP settings reset after rebootKernel parameters not persistentCheck GRUB configuration and run sudo update-grub (Ubuntu) or sudo grub2-mkconfig (RHEL)
High memory fragmentationTHP disabled without memory optimizationApply database-specific sysctl settings in /etc/sysctl.d/
Database performance degraded after THP disableMissing memory allocation tuningConfigure vm.overcommit_memory and vm.swappiness for your database type
Memory pressure alertsInsufficient RAM for workloadAdd more memory or tune database memory limits using memory-pressure-check.sh
THP monitoring not workingSystemd timer not enabledsudo systemctl enable --now thp-monitor.timer
NUMA performance issuesZone reclaim enabledSet vm.zone_reclaim_mode = 0 in sysctl configuration
Never use chmod 777. When fixing permission issues with log files or scripts, use specific

Automated install script

Run this to automate the entire setup

Don't want to manage this yourself?

We handle infrastructure for businesses that depend on uptime. Fully managed, with one fixed contact who knows your setup.

You get one fixed contact who knows your setup

Rotterdam 12:58 · reachable in a message, no ticket form