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:
- Increase SHMMAX/SHMALL further
- Reduce PostgreSQL's shared_buffers setting
- 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