PostgreSQL Performance Tuning: SHMMAX and SHMALL Configuration Guide for Linux Systems


9 views

When tuning PostgreSQL performance on Linux systems, two critical kernel parameters stand out: SHMMAX and SHMALL. These control the maximum size of a single shared memory segment and the total shared memory allocation respectively.

The confusion stems from different Linux distributions interpreting SHMALL differently:

  • SHMMAX is always measured in bytes
  • SHMALL can be measured in either pages or bytes

On Debian-based systems like Ubuntu, SHMALL is measured in pages (typically 4KB each). You can verify this by checking your system's page size:

getconf PAGE_SIZE

For a PostgreSQL server with 16GB RAM, here's how to calculate values:

# SHMMAX (bytes)
echo $((16 * 1024 * 1024 * 1024 / 4)) > /proc/sys/kernel/shmmax

# SHMALL (pages)
PAGE_SIZE=$(getconf PAGE_SIZE)
echo $((16 * 1024 * 1024 * 1024 / 2 / $PAGE_SIZE)) > /proc/sys/kernel/shmall

To make these changes persistent across reboots, add to /etc/sysctl.conf:

kernel.shmmax = 4294967296
kernel.shmall = 1048576

After applying changes, verify with:

sysctl -a | grep -E 'shmmax|shmall'

If PostgreSQL fails to start, check logs for shared memory errors. Common issues include:

  • Setting SHMMAX higher than available RAM
  • Forgetting to convert SHMALL to pages
  • Not accounting for other processes' memory needs

For systems with huge pages enabled, adjust calculations accordingly. Also consider:

vm.nr_hugepages = X
vm.hugetlb_shm_group = postgres

PostgreSQL relies heavily on shared memory for various operations including:

  • Shared buffers (for caching data)
  • WAL buffers (for write-ahead logging)
  • Lock space and other internal structures

The key difference between these parameters:

SHMMAX - Maximum size of a single shared memory segment (bytes)
SHMALL - Total amount of shared memory system-wide (pages or bytes)

On Debian-based systems like Ubuntu, SHMALL is measured in pages, not bytes. To verify your system's page size:

getconf PAGE_SIZE
# Typical output: 4096 (4KB)

For a server with 16GB RAM:

# Calculate SHMMAX (bytes)
echo $((16 * 1024 * 1024 * 1024 / 4)) → 4294967296 (4GB)

# Calculate SHMALL (pages)
PAGE_SIZE=$(getconf PAGE_SIZE)
echo $((16 * 1024 * 1024 * 1024 / 2 / $PAGE_SIZE)) → 2097152

Add these lines to /etc/sysctl.conf:

kernel.shmmax = 4294967296
kernel.shmall = 2097152

Apply changes immediately:

sudo sysctl -p

Check current values:

sysctl kernel.shmmax kernel.shmall
ipcs -lm

If PostgreSQL fails to start with "could not create shared memory segment" errors, you may need to:

  1. Increase SHMMAX/SHMALL further
  2. Reduce PostgreSQL's shared_buffers setting
  3. Consider using huge pages (vm.nr_hugepages)

While the /4 and /2 rule works for most cases, consider:

  • On dedicated PostgreSQL servers: SHMMAX = 50-75% of RAM
  • When using huge pages: Adjust calculations accordingly
  • For systems with multiple instances: Divide available memory