Course contentsShow
← Databases & SQL
Lesson 880 of 1,9538. PostgreSQL InternalsFree lesson

Shared Memory Communication in Extensions

You will utilize shared memory for communication between extension processes.

In this lesson, you will learn how to design custom PostgreSQL extensions that exchange data between multiple backend processes using a shared memory segment.

The Problem: Process Isolation

PostgreSQL is a multi-process architecture. Each client connection is handled by a separate "backend" process that does not share its local memory with others. If you want two separate sessions to coordinate state—such as tracking a custom counter or maintaining a global configuration cache—local variables won't work. Instead, you must allocate a block of memory during server startup that persists globally across the entire database cluster.

Mechanism: shmem_request_hook and ShmemInitStruct

To facilitate this communication, your extension must hook into the server’s initialization phase.

  1. Requesting Memory: You use the shmem_request_hook to reserve a specific amount of bytes. PostgreSQL allocates this block when the postmaster process starts.
  2. Accessing the Block: Once the server is running, your backend processes call ShmemInitStruct. This function looks up the named shared memory block. If it doesn't exist, it creates it; otherwise, it returns a pointer to the existing segment.

Code Illustration

Imagine you want to store a global int32 counter. In your C code, you would define a struct to hold your state and map it to shared memory:

typedef struct {
    int32 global_counter;
    LWLockId lock; // Crucial for concurrency
} MyExtensionData;

static MyExtensionData *my_data;

void MyExtensionInit(void) {
    bool found;
    my_data = ShmemInitStruct("my_extension_data", sizeof(MyExtensionData), &found);
    if (!found) {
        my_data->global_counter = 0;
        my_data->lock = LWLockAssign(); // Initialize a lightweight lock
    }
}

Critical Considerations

Because multiple processes will attempt to read and write to this memory block simultaneously, you must use PostgreSQL’s LWLock (Lightweight Lock) mechanism. Without locks, your extension will encounter race conditions, leading to data corruption or crashes. Treat the memory as a "critical section" where only one process can read or modify the values at a time, ensuring atomicity across the entire cluster.

Key Takeaway: Shared memory provides a high-performance, cross-process communication channel, but it requires manual memory allocation during startup and strict adherence to LWLock synchronization to prevent data races.