Shared Memory Cache Subsystem
Overview
The Shared Memory Cache Subsystem enables efficient inter-process communication (IPC) between the XID Manager daemon, the PgXidSubscriberMgr daemon, and PostgreSQL Foreign Data Wrapper (FDW) processes. This subsystem allows multiple FDW processes to share system metadata and transaction mutation data without repeated RPC calls to backend services.Key Benefits
- Zero-copy data sharing between processes using Boost Interprocess shared memory
- Reduced RPC overhead by caching frequently accessed metadata locally
- Transaction-aware caching with XID (transaction ID) history tracking
- Automatic staleness detection and cache refresh mechanisms
- LRU-based memory management to prevent unbounded growth
Architecture
High-Level Data Flow
Components
| Component | Role | Process Type |
|---|---|---|
| PgXidSubscriberMgr | Cache producer - creates and maintains caches | Daemon thread |
| PgFdwMgr | Cache consumer - opens and uses caches | PostgreSQL FDW process |
| ShmCache | Shared memory abstraction using Boost Interprocess | Library class |
| MsgCache | Multi-index container with LRU eviction | Template class |
| XidMgrClient | Streams XID commit notifications | gRPC client |
Cache Types
The subsystem manages 5 distinct shared memory caches, each serving a specific purpose:1. Roots Cache (SHM_CACHE_ROOTS)
Purpose: Stores table root/metadata information Key Properties:- XID history: Enabled
- Tracks schema changes across transactions
- Contains table root objects with metadata pointers
- Created:
pg_xid_subscriber_mgr.cc:53 - Used by:
sys_tbl_mgr::Client::get_roots()
2. Schema Cache (SHM_CACHE_SCHEMAS)
Purpose: Stores table schema definitions Key Properties:- XID history: Disabled
- Contains column definitions, types, constraints
- Updated on DDL operations
- Created:
pg_xid_subscriber_mgr.cc:56 - Used by:
sys_tbl_mgr::Client::get_schema()
3. UserType Cache (SHM_CACHE_USERTYPES)
Purpose: Stores user-defined type information Key Properties:- XID history: Disabled
- Contains custom type definitions
- Required for schema deserialization
- Created:
pg_xid_subscriber_mgr.cc:61 - Used by:
sys_tbl_mgr::Client::get_usertype()
4. Table IDs Cache (SHM_CACHE_TABLE_IDS)
Purpose: Maps (DbId, XID) to list of TableIds modified in each transaction Key Properties:- XID history: Enabled
- Tracks pending mutations per transaction
- Critical for read-after-write consistency
- Created:
pg_xid_subscriber_mgr.cc:64 - Used by:
PgFdwMgr::_get_table():645-654
5. Extents Cache (SHM_CACHE_EXTENTS)
Purpose: Stores mutation records (extents) from WriteCacheClient Key Properties:- XID history: Disabled
- Contains actual data mutations
- Populated before applying to base tables
- Created:
pg_xid_subscriber_mgr.cc:68 - Used by:
WriteCacheClientfor mutation staging
Detailed Component Documentation
PgXidSubscriberMgr
Header:include/pg_fdw/pg_xid_subscriber_mgr.hh:22-105
Implementation: src/pg_fdw/pg_xid_subscriber_mgr.cc
Responsibilities
-
Cache Creation (
init()method):- Creates all 5 shared memory caches with configured sizes
- Removes stale caches from previous runs
- Initializes XID history cleaners for enabled caches
-
XID Push Notification Handling (
task()method):- Subscribes to XidMgrClient push stream
- Receives
proto::XidPushResponsemessages - Dispatches based on
real_commitflag
-
Asynchronous Population (worker threads):
- Configurable thread pool size
- Fetches metadata on transaction commit
- Calls
Client::get_roots(),get_schema(),get_usertype() - Automatically populates caches via registered ShmCache instances
PgFdwMgr
Header:include/pg_fdw/pg_fdw_mgr.hh:133-468
Implementation: src/pg_fdw/pg_fdw_mgr.cc
Responsibilities
-
Cache Opening (
_try_create_cache()method):- Opens existing caches created by PgXidSubscriberMgr
- Verifies cache liveness with
is_alive()check - Registers caches with Client and WriteCacheClient singletons
-
Mutation Application (
_get_table()method):- Queries pending XIDs since last committed
- Fetches mutation metadata from table_ids_cache
- Retrieves extent data from WriteCache
- Applies mutations to base table as ChangeSet
-
Lifecycle Management:
- Lazy initialization on first query
- Automatic cache reopening if stale
- Background thread for XID updates
- Opens in read mode (size=0 parameter)
- Handles case where PgXidSubscriberMgr hasn’t started yet
- Checks
is_alive()to detect stale caches - Registers with appropriate singleton clients
- Only processes
XIDs <= snapshot_xid(transaction isolation) - Limits to
MAX_WRITE_CACHE_EXTENTS(10) per query - Resets pending XIDs if too many extents found
- Avoids redundant extent fetches
ShmCache Class
Header:include/sys_tbl_mgr/shm_cache.hh:73-360
Implementation: src/sys_tbl_mgr/shm_cache.cc
Purpose
Provides a shared memory abstraction using Boost Interprocess for inter-process data sharing.Key Features
-
Dual-mode construction:
- Create mode:
ShmCache(type, size, xid_history)with size > 0 - Open mode:
ShmCache(type, 0, xid_history)opens existing cache
- Create mode:
-
XID tracking (if enabled):
- Tracks committed XID per database
- Maintains list of pending XIDs
- Records XID history for schema changes
-
Keep-alive mechanism:
- Caches must be kept alive every 60ms
is_alive()checks if cache is stale- Automatic reconnection if stale detected
- PgXidSubscriberMgr calls
keep_alive()every 60ms - PgFdwMgr checks
is_alive()before using cache - If stale, PgFdwMgr reopens cache
MsgCache Template
Header:include/sys_tbl_mgr/msg_cache.hh:31-323
Purpose
Multi-index container with LRU eviction, providing both fast lookup and insertion-order tracking. Configuration:- Free memory limit: 30% (trigger eviction)
- Free memory watermark: 50% (stop eviction)
- Retention: Top 10% frequently accessed items protected (
msg_cache.hh:236)
Synchronization and Concurrency
Thread Safety Strategy
Mutex Hierarchy
Configuration
Configuration Properties
File: Properties singleton (commonly loaded from YAML/JSON config) Schema:| Parameter | Type | Default | Description |
|---|---|---|---|
roots_shm_cache_size | size_t | 1 GB | Size of roots cache in bytes |
schema_shm_cache_size | size_t | 512 MB | Size of schema cache in bytes |
usertype_shm_cache_size | size_t | 256 MB | Size of usertype cache in bytes |
table_ids_shm_cache_size | size_t | 512 MB | Size of table IDs cache in bytes |
extents_shm_cache_size | size_t | 1 GB | Size of extents cache in bytes |
server_worker_threads | size_t | 4 | Number of worker threads for async population |
Usage Examples
Example 1: Querying Table with Pending Mutations
Scenario: PostgreSQL FDW process executesSELECT * FROM table WHERE id = 123 with snapshot XID 1000.
Steps:
Example 3: Cache Staleness Detection and Recovery
Scenario: PgXidSubscriberMgr crashes and restarts while FDW processes are running. Steps:4. LRU Eviction Strategy
Problem: Unbounded cache growth causes OOM Solution: Multi-index container with sequenced index for LRU Benefits:- Automatic eviction at 30% free memory
- Stops eviction at 50% free memory watermark
Debugging Commands
1. Producer-Consumer with Lazy Initialization
Pattern:- Producer: PgXidSubscriberMgr creates and maintains caches
- Consumer: PgFdwMgr opens and uses caches
- Trigger: Query execution in PostgreSQL FDW process
- Loose coupling between producer and consumer
- Graceful handling of startup ordering
- Automatic recovery on producer restart
References
Source Files
| File | Description |
|---|---|
include/pg_fdw/pg_xid_subscriber_mgr.hh | PgXidSubscriberMgr class definition |
src/pg_fdw/pg_xid_subscriber_mgr.cc | PgXidSubscriberMgr implementation |
include/pg_fdw/pg_fdw_mgr.hh | PgFdwMgr class definition |
src/pg_fdw/pg_fdw_mgr.cc | PgFdwMgr implementation |
include/sys_tbl_mgr/shm_cache.hh | ShmCache class definition |
src/sys_tbl_mgr/shm_cache.cc | ShmCache implementation |
include/sys_tbl_mgr/msg_cache.hh | MsgCache template definition |
src/proto/xid_manager.proto | XidPushResponse protobuf definition |
include/write_cache/write_cache_client.hh | WriteCacheClient class definition |
External Dependencies
| Library | Purpose | Documentation |
|---|---|---|
| Boost Interprocess | Shared memory IPC | boost.org/doc/libs/interprocess |
| Boost Multi-Index | Multi-index containers | boost.org/doc/libs/multi_index |
| Protocol Buffers | Serialization | developers.google.com/protocol-buffers |
| gRPC | RPC framework | grpc.io |
Related Documentation
- PostgreSQL Foreign Data Wrapper API
- Springtail Transaction Management
- XID Manager Architecture
- WriteCache Design