Optimal Configuration of Shared Memory Parameters (shmall, shmmax) for PostgreSQL Performance Tuning


2 views

Shared memory is a critical resource for database systems like PostgreSQL that heavily rely on inter-process communication. The key parameters controlling shared memory allocation are:

kernel.shmmax - Maximum size of a single shared memory segment (bytes)
kernel.shmall - Total available shared memory pages system-wide
kernel.shmmni - Maximum number of shared memory segments

Based on your system with 16GB RAM (16345480 kB MemTotal), your calculations are generally correct:

# For kernel.shmmax (80% of physical RAM)
16GB * 0.8 = 13.1GB → 4420419584 bytes (your value)

# For kernel.shmall (Total pages = shmmax/PAGE_SIZE)
Typically PAGE_SIZE=4096 → 4420419584/4096 = 1079204 (your value)

Your PostgreSQL configuration looks reasonable, but consider these adjustments:

# More aggressive settings for write-heavy workloads
shared_buffers = 6GB            # Up to 25% of RAM for dedicated DB servers
wal_buffers = 16MB              # Default 8MB often too small
maintenance_work_mem = 512MB    # For VACUUM and CREATE INDEX
random_page_cost = 1.1          # For SSD storage

After applying changes, verify with these commands:

# Check current shared memory limits
cat /proc/sys/kernel/shmall
cat /proc/sys/kernel/shmmax

# PostgreSQL shared memory usage
SELECT pg_size_pretty(pg_shmem_allocations()::bigint);

For mission-critical systems, add these to /etc/sysctl.conf:

# Additional stability parameters
vm.swappiness = 1               # Reduce swapping tendency
vm.overcommit_memory = 2        # Strict memory allocation policy
vm.overcommit_ratio = 95        # Allow 95% of RAM for allocations

For systems handling 1000+ TPS:

# Increase system-wide semaphores
kernel.sem = 500 64000 200 1024
# SEMMNI SEMMSL SEMMNS SEMOPM

# PostgreSQL WAL configuration
wal_level = replica             # For replication setups
max_wal_senders = 8             # Allow multiple replicas
checkpoint_timeout = 15min      # Reduce I/O spikes

When configuring PostgreSQL on Linux systems, three critical kernel parameters require careful attention:

  • SHMMAX: Maximum size of a single shared memory segment (bytes)
  • SHMALL: Total available shared memory system-wide (pages)
  • SHMMNI: Maximum number of shared memory segments

For a system with 16GB RAM (16345480 kB as shown in your meminfo):

# Calculate SHMMAX (recommended: 50-70% of RAM)
SHMMAX = 16345480 kB * 50% = 8172740 kB → 8372906240 bytes

# Calculate SHMALL (total pages)
SHMALL = SHMMAX / page_size (typically 4096 bytes)
       = 8372906240 / 4096 ≈ 2044169 pages

The shared_buffers parameter in postgresql.conf directly affects shared memory requirements:

# Recommended calculation:
shared_buffers = 25% of RAM (for dedicated DB servers)
               = 0.25 * 16345480 kB ≈ 4GB (as you've configured)

Permanent configuration via /etc/sysctl.conf:

# PostgreSQL optimized settings
kernel.shmmax = 8372906240
kernel.shmall = 2044169
kernel.shmmni = 4096
kernel.sem = 250 32000 32 128
fs.file-max = 65536

Apply changes immediately:

sysctl -p

Verify current limits with:

ipcs -l
sysctl -a | grep shm

PostgreSQL shared memory usage check:

SELECT * FROM pg_shmem_allocations;

If encountering "No space left on device" errors despite available memory:

# Check actual usage vs limits
cat /proc/sysvipc/shm

For containerized environments, ensure proper namespace permissions:

docker run --shm-size=8g postgres:latest