Troubleshooting PostgreSQL shared_buffers Memory Limit Configuration Crash on CentOS Stream / Rocky Linux
Resolve PostgreSQL crashes on CentOS/Rocky Linux caused by insufficient shared_buffers memory limits. Learn to adjust kernel parameters and PostgreSQL configuration for stability.
Resolve PostgreSQL crashes on CentOS/Rocky Linux caused by insufficient shared_buffers memory limits. Learn to adjust kernel parameters and PostgreSQL configuration for stability.
PostgreSQL is a powerful object-relational database system, but like any complex software, it requires careful configuration, especially concerning memory management. A common issue encountered by administrators on CentOS Stream or Rocky Linux environments is PostgreSQL failing to start or crashing unexpectedly due to insufficient System V shared memory limits for its shared_buffers configuration. This guide will walk you through diagnosing and resolving this critical memory allocation error.
Symptom & Error Signature
When PostgreSQL encounters an issue allocating shared_buffers, your database service will typically fail to start or crash during operation. You'll observe applications failing to connect to the database, and the PostgreSQL service will show a "failed" status.
Typical error messages found in journalctl -u postgresql-<VERSION_NUMBER> or the PostgreSQL data directory logs (pg_log/):
FATAL: could not create shared memory segment: Cannot allocate memory
DETAIL: Failed system call was shmget(KEY, SIZE, 0600).
HINT: This error usually means that PostgreSQL's request for a shared memory segment exceeded available RAM or Linux's system-wide shared memory limit. You might need to reduce the amount of shared memory requested by PostgreSQL, or reconfigure the kernel to allow more. See Linux's shmmax and shmall parameters.
Another possible signature related to semaphores, though less common for this specific shared_buffers issue:
FATAL: could not create semaphores: No space left on device
DETAIL: Failed system call was semget(KEY, N, 0300).
HINT: This error does *not* mean you have run out of disk space. It occurs when the OS has run out of System V semaphore sets, or values for semaphores. You might need to increase the kernel's SHMMNI, SHMALL, and SEMMNS parameters.
If the system experiences severe memory pressure, you might also see messages from the Out-Of-Memory (OOM) Killer in dmesg or journalctl -k output:
kernel: Out of memory: Killed process 1234 (postgres) score 999
kernel: oom-kill:constraint=CC-GROUP,node=0,cpuset=/user.slice,mems_allowed=0,oom_score_adj=0
Root Cause Analysis
The core of this problem lies in how PostgreSQL allocates its main memory cache, shared_buffers, and how the Linux kernel manages System V shared memory segments.
shared_buffers: This critical PostgreSQL parameter defines the amount of dedicated memory for caching data pages. A largershared_buffersvalue generally improves database performance by reducing disk I/O. By default, PostgreSQL often suggests values around 25% of total system RAM, up to 8GB or more on systems with ample memory.System V Shared Memory: On Linux,
shared_bufferstypically uses System V shared memory segments (SHM). The kernel imposes limits on these segments to prevent a single process from monopolizing system resources or to ensure system stability. The two most relevant kernel parameters are:kernel.shmmax: Defines the maximum size (in bytes) of a single shared memory segment that the kernel will allow. If your configuredshared_buffersvalue inpostgresql.confexceeds this limit, PostgreSQL will fail to allocate it.kernel.shmall: Defines the total amount of shared memory (in system pages) that can be allocated on the system at any given time. This is less frequently the direct cause of a crash for a single largeshared_buffersallocation but can contribute if many processes are using shared memory or ifshmmaxis sufficiently large. A "page" size is typically 4096 bytes (4KB).
CentOS/Rocky Linux Defaults: CentOS Stream and Rocky Linux often come with conservative default
kernel.shmmaxandkernel.shmallvalues. For instance,shmmaxmight be set to18446744073692774399(a very large number, practically infinite), butshmallmight be limited. More commonly, if you're hitting issues, it's due to anshmmaxthat's too low for a significantly increasedshared_buffersvalue, or simply not enough available RAM for the allocation.Allocation Failure: When PostgreSQL attempts to start, it requests a shared memory segment of the size specified by
shared_buffers. If this request exceedskernel.shmmax, or if there isn't enough physical memory available to back the segment (even ifshmmaxis high), theshmget()system call will fail, leading to the "Cannot allocate memory" error.OOM Killer: In rare cases, if PostgreSQL manages to start but the combined memory usage (including
shared_buffers,work_mem, client connections, and other system processes) exceeds available RAM, the Linux Out-Of-Memory (OOM) Killer might terminate the PostgreSQL process to free up memory, leading to an unexpected crash.
Step-by-Step Resolution
Follow these steps to diagnose and correctly configure your system and PostgreSQL for stable operation.
1. Assess Current System Memory & PostgreSQL Configuration
First, gather information about your system's memory and current PostgreSQL settings.
# Check total system RAM
free -h
# Check current kernel shared memory parameters
sysctl -a | grep shm
# Find your PostgreSQL data directory and version (example for PG 14)
# You might need to adjust the service name based on your installation
sudo systemctl status postgresql-14
# The output will show something like:
# Active: active (running) since ...
# Docs: https://www.postgresql.org/docs/14/static/
# Process: 1234 ExecStart=/usr/bin/postmaster ... -D /var/lib/pgsql/14/data (code=exited, status=0/SUCCESS)
# Main PID: 5678 (postmaster)
# Check your postgresql.conf for shared_buffers (replace with your actual data directory path)
# Example: If data directory is /var/lib/pgsql/14/data
grep shared_buffers /var/lib/pgsql/14/data/postgresql.conf
Note down the shared_buffers value you intend to use or currently have configured, and your system's total RAM.
2. Calculate Required Kernel Shared Memory Parameters
Based on your desired shared_buffers size, calculate the appropriate kernel.shmmax and kernel.shmall values.
The
shared_buffersvalue should generally be between 15-25% of your total system RAM. Going much higher (e.g., 40%+) can be detrimental, as it can lead to double-buffering (OS page cache vs. PostgreSQL cache) and potentially less RAM for other processes. For very large RAM systems (64GB+), consider an upper bound of 8-16GB forshared_buffersand rely more on the OS page cache for remaining data.
Let's assume you want to set shared_buffers to 8GB (8192MB).
kernel.shmmax: This must be at least the size of yourshared_buffers. It's generally safe to set it slightly higher or to a significant fraction of your total RAM.- Desired
shared_buffers= 8 GB =8 * 1024 * 1024 * 1024bytes =8589934592bytes. - So,
kernel.shmmaxshould be at least8589934592. We can round up to a power of 2 or a convenient number, e.g.,8589934592bytes.
- Desired
kernel.shmall: This represents the total shared memory in pages. The default page size on x86-64 Linux is typically 4096 bytes (4KB).- Total shared memory (in bytes) =
kernel.shmmax(or slightly more if you expect other SHM usage) kernel.shmall=kernel.shmmax/PAGE_SIZEkernel.shmall=8589934592/4096=2097152
- Total shared memory (in bytes) =
So, for an 8GB shared_buffers setting, you'd need:
kernel.shmmax = 8589934592
kernel.shmall = 2097152
3. Adjust Kernel Parameters
To make these changes persistent across reboots, you should create a new sysctl configuration file.
# Create or edit a sysctl configuration file for PostgreSQL
sudo vi /etc/sysctl.d/99-postgresql.conf
Add the following lines to the file, replacing the values with your calculated ones:
# PostgreSQL shared_buffers configuration
kernel.shmmax = 8589934592
kernel.shmall = 2097152
While it's generally safe to set
shmmaxto a very large value (e.g., half of your RAM or more), ensureshmallis also appropriately set. Incorrectly highshmallwith limited physical RAM can lead to system instability or the OOM Killer being invoked. Always ensure your total configuredshared_buffersacross all PostgreSQL instances (if more than one) plus other memory-consuming processes fit within your physical RAM.
Apply the changes immediately without rebooting:
sudo sysctl -p /etc/sysctl.d/99-postgresql.conf
Verify that the new values are active:
sysctl -a | grep shm
You should see output similar to:
kernel.shmmax = 8589934592
kernel.shmall = 2097152
4. Verify PostgreSQL shared_buffers Configuration
Now that the kernel can accommodate the larger shared memory segment, adjust your postgresql.conf if necessary.
# Open your postgresql.conf file (adjust path for your PostgreSQL version)
sudo vi /var/lib/pgsql/14/data/postgresql.conf
Find the shared_buffers line and ensure it's uncommented and set to your desired value (e.g., 8GB).
# shared_buffers = 128MB # min 128kB
shared_buffers = 8GB # Example: for an 8GB setting
While adjusting
shared_buffers, also considereffective_cache_size. This parameter informs PostgreSQL about the total amount of memory available for caching (including the OS page cache). It should typically be set to 50-75% of your total RAM. This parameter does not allocate memory itself but influences the query planner. For example, if you have 16GB RAM and setshared_buffers = 4GB, you might seteffective_cache_size = 12GB.
# effective_cache_size = 4GB
effective_cache_size = 12GB # Example for 16GB RAM, 4GB shared_buffers
Save and close the postgresql.conf file.
5. Restart PostgreSQL Service
With kernel parameters and postgresql.conf updated, restart PostgreSQL.
# Replace '14' with your PostgreSQL version
sudo systemctl restart postgresql-14
Check the service status to ensure it started successfully:
sudo systemctl status postgresql-14
If it shows active (running), you're good to go. If not, carefully review the logs again (journalctl -u postgresql-14) for new errors.
6. Verify Post-Restart
Finally, connect to your PostgreSQL database and confirm the shared_buffers setting.
# Connect as the postgres user (or your superuser)
sudo -i -u postgres psql
# In the psql prompt, check the setting
SHOW shared_buffers;
The output should reflect your configured value:
shared_buffers
----------------
8GB
(1 row)
You have now successfully configured PostgreSQL's shared_buffers and the Linux kernel's shared memory parameters to prevent crashes due to memory allocation limits. Always monitor your system's memory usage to ensure optimal performance and stability.