From cd2fd975382c629a5fa825a32a1b35e485564001 Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat Date: Mon, 1 Sep 2025 15:40:41 +0530 Subject: [PATCH 12/16] Initial value of shared_buffers (or NBuffers) The assign_hook for shared_buffers (assign_shared_buffers()) is called twice during server startup. First time it sets the default value of shared_buffers, followed by a second time when it sets the value specified in the configuration file or on the command line. At those times the shared buffer pool is yet to be initialized. Hence there is no need to keep the GUC change pending or going through the entire process of resizing memory maps, reinitializing the shared memory and process synchronization. Instead the given value should be assigned directly to NBuffers, which will be used when creating the shared memory and also when initializing the buffer pool the first time. Any changes to shared_buffer after that will need remapping the shared memory segment and synchronize buffer pool reinitialization across the backends. If BufferBlocks is not initilized assign_shared_buffers() sets the given value to NBuffers directly. Otherwise it marks the change as pending and sets the flag pending_pm_shmem_resize so that Postmaster can start the buffer pool reinitialization. TODO: 1. The change depends upon the C convention that the global pointer variables being initialized to NULL. May be initialize BufferBlocks to NULL explicitly. 2. We might think of a better way to check whether buffer pool has been initialized or not. See comment in assign_shared_buffers(). Author: Ashutosh Bapat --- src/backend/port/sysv_shmem.c | 42 ++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c index dc4eeeee56a..ba8613678f6 100644 --- a/src/backend/port/sysv_shmem.c +++ b/src/backend/port/sysv_shmem.c @@ -1168,20 +1168,42 @@ ProcessBarrierShmemResize(Barrier *barrier) } /* - * GUC assign hook for shared_buffers. It's recommended for an assign hook to - * be as minimal as possible, thus we just request shared memory resize and - * remember the previous value. + * GUC assign hook for shared_buffers. + * + * When setting the GUC first time after starting the server, the GUC value is + * changed immediately since there is not shared memory setup yet. + * + * After the shared memory is setup, changing the GUC value requires resizing and + * reiniatializing (at least parts of) the shared memory structures related to + * shared buffers. That's a long and complicated process. It's recommended for + * an assign hook to be as minimal as possible, thus we just request shared + * memory resize and remember the previous value. */ void assign_shared_buffers(int newval, void *extra, bool *pending) { - elog(DEBUG1, "Received SIGHUP for shmem resizing"); - - pending_pm_shmem_resize = true; - *pending = true; - NBuffersPending = newval; - - NBuffersOld = NBuffers; + /* + * TODO: If a backend joins while the buffer resizing is in progress or it + * reads a value of shared_buffers from configuration which is different from + * the value being used by existing backends, this method may not work. Need + * to think of a better solution. + */ + if (BufferBlocks) + { + elog(DEBUG1, "bufferpool is already initialized with size = %d, reinitializing it with size = %d", + NBuffers, newval); + pending_pm_shmem_resize = true; + *pending = true; + NBuffersPending = newval; + NBuffersOld = NBuffers; + } + else + { + elog(DEBUG1, "initializing buffer pool with size = %d", newval); + NBuffers = newval; + *pending = false; + pending_pm_shmem_resize = false; + } } /* -- 2.34.1