引言
9.3版本以前,调整共享内存大小常常需要调整内核参数以适应更改。9.3之后的版本已经不需要了。

匿名共享内存
装了一个9.0.9版本 不支持 Support for anonymous shared memorypostgres=# select version();version-------------------------------------------------------------------------------------------------------------------PostgreSQL 9.0.9 on x86_64-unknown-linux-gnu, compiled by GCC gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit(1 row)通过smem查询[root@pg01 ~]# smem -U postgres -k |head -1;smem -U postgres -k |grep -i postgres |sort -k 1 -n -rPID User Command Swap USS PSS RSS87635 postgres postgres: postgres postgres 0 3.6M 4.6M 6.5M87634 postgres psql -h 127.0.0.1 -p 5432 p 0 876.0K 908.0K 1.9M87590 postgres postgres: stats collector p 0 148.0K 233.0K 968.0K87589 postgres postgres: autovacuum launch 0 756.0K 1.0M 2.1M87588 postgres postgres: wal writer proces 0 128.0K 268.0K 1.1M87587 postgres postgres: writer process 0 204.0K 1.7M 4.1M87585 postgres postgres: logger process 0 136.0K 200.0K 828.0K87584 postgres opt/pgsql9.09/bin/postgres 0 138.3M 140.3M 143.8M87479 postgres -bash 0 1.7M 1.9M 3.4M切换到12.8版本PostgreSQLpostgres=# select version();version---------------------------------------------------------------------------------------------------------PostgreSQL 12.8 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit(1 row)postgres=#通过smem查询[root@pg01 ~]# smem -U postgres -k |head -1;smem -U postgres -k |grep -i postgres |sort -k 1 -n -rPID User Command Swap USS PSS RSS87852 postgres postgres: postgres postgres 0 2.6M 3.2M 5.4M87851 postgres psql 0 1.3M 1.4M 3.1M87850 postgres postgres: logical replicati 0 476.0K 710.0K 2.3M87849 postgres postgres: stats collector 0 216.0K 336.0K 1.6M87848 postgres postgres: autovacuum launch 0 564.0K 856.0K 2.6M87847 postgres postgres: walwriter 0 220.0K 60.4M 121.7M87846 postgres postgres: background writer 0 224.0K 617.0K 2.2M87845 postgres postgres: checkpointer 0 168.0K 292.0K 1.6M87843 postgres postgres: logger 0 172.0K 291.0K 1.5M87842 postgres opt/pgsql12.8/bin/postgres 0 32.7M 93.7M 157.2M87479 postgres -bash 0 1.7M 1.9M 3.4M
src/backend/storage/ipc/shmem.cshmem index table 类型是 hash table/*-------------------------------------------------------------------------** shmem.c* create shared memory and initialize shared memory data structures.** Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group* Portions Copyright (c) 1994, Regents of the University of California*** IDENTIFICATION* src/backend/storage/ipc/shmem.c**-------------------------------------------------------------------------*//** POSTGRES processes share one or more regions of shared memory.* The shared memory is created by a postmaster and is inherited* by each backend via fork() (or, in some ports, via other OS-specific* methods). The routines in this file are used for allocating and* binding to shared memory data structures.** NOTES:* (a) There are three kinds of shared memory data structures* available to POSTGRES: fixed-size structures, queues and hash* tables. Fixed-size structures contain things like global variables* for a module and should never be allocated after the shared memory* initialization phase. Hash tables have a fixed maximum size, but* their actual size can vary dynamically. When entries are added* to the table, more space is allocated. Queues link data structures* that have been allocated either within fixed-size structures or as hash* buckets. Each shared data structure has a string name to identify* it (assigned in the module that declares it).** (b) During initialization, each module looks for its* shared data structures in a hash table called the "Shmem Index".* If the data structure is not present, the caller can allocate* a new one and initialize it. If the data structure is present,* the caller "attaches" to the structure by initializing a pointer* in the local address space.* The shmem index has two purposes: first, it gives us* a simple model of how the world looks when a backend process* initializes. If something is present in the shmem index,* it is initialized. If it is not, it is uninitialized. Second,* the shmem index allows us to allocate shared memory on demand* instead of trying to preallocate structures and hard-wire the* sizes and locations in header files. If you are using a lot* of shared memory in a lot of different places (and changing* things during development), this is important.** (c) In standard Unix-ish environments, individual backends do not* need to re-establish their local pointers into shared memory, because* they inherit correct values of those variables via fork() from the* postmaster. However, this does not work in the EXEC_BACKEND case.* In ports using EXEC_BACKEND, new backends have to set up their local* pointers using the method described in (b) above.** (d) memory allocation model: shared memory can never be* freed, once allocated. Each hash table has its own free list,* so hash buckets can be reused when an item is deleted. However,* if one hash table grows very large and then shrinks, its space* cannot be redistributed to other tables. We could build a simple* hash bucket garbage collector if need be. Right now, it seems* unnecessary.*/#include "postgres.h"#include "access/transam.h"#include "miscadmin.h"#include "storage/lwlock.h"#include "storage/pg_shmem.h"#include "storage/shmem.h"#include "storage/spin.h"/* shared memory global variables */static PGShmemHeader *ShmemSegHdr; /* shared mem segment header */static void *ShmemBase; /* start address of shared memory */static void *ShmemEnd; /* end+1 address of shared memory */slock_t *ShmemLock; /* spinlock for shared memory and LWLock* allocation */static HTAB *ShmemIndex = NULL; /* primary index hashtable for shmem *//** InitShmemAccess() --- set up basic pointers to shared memory.** Note: the argument should be declared "PGShmemHeader *seghdr",* but we use void to avoid having to include ipc.h in shmem.h.*/voidInitShmemAccess(void *seghdr){PGShmemHeader *shmhdr = (PGShmemHeader *) seghdr;ShmemSegHdr = shmhdr;ShmemBase = (void *) shmhdr;ShmemEnd = (char *) ShmemBase + shmhdr->totalsize;}/** InitShmemAllocation() --- set up shared-memory space allocation.** This should be called only in the postmaster or a standalone backend.*/voidInitShmemAllocation(void){PGShmemHeader *shmhdr = ShmemSegHdr;char *aligned;Assert(shmhdr != NULL);/** Initialize the spinlock used by ShmemAlloc. We must use* ShmemAllocUnlocked, since obviously ShmemAlloc can't be called yet.*/ShmemLock = (slock_t *) ShmemAllocUnlocked(sizeof(slock_t));SpinLockInit(ShmemLock);/** Allocations after this point should go through ShmemAlloc, which* expects to allocate everything on cache line boundaries. Make sure the* first allocation begins on a cache line boundary.*/aligned = (char *)(CACHELINEALIGN((((char *) shmhdr) + shmhdr->freeoffset)));shmhdr->freeoffset = aligned - (char *) shmhdr;/* ShmemIndex can't be set up yet (need LWLocks first) */shmhdr->index = NULL;ShmemIndex = (HTAB *) NULL;/** Initialize ShmemVariableCache for transaction manager. (This doesn't* really belong here, but not worth moving.)*/ShmemVariableCache = (VariableCache)ShmemAlloc(sizeof(*ShmemVariableCache));memset(ShmemVariableCache, 0, sizeof(*ShmemVariableCache));}/** ShmemAlloc -- allocate max-aligned chunk from shared memory** Throws error if request cannot be satisfied.** Assumes ShmemLock and ShmemSegHdr are initialized.*/void *ShmemAlloc(Size size){void *newSpace;newSpace = ShmemAllocNoError(size);if (!newSpace)ereport(ERROR,(errcode(ERRCODE_OUT_OF_MEMORY),errmsg("out of shared memory (%zu bytes requested)",size)));return newSpace;}/** ShmemAllocNoError -- allocate max-aligned chunk from shared memory** As ShmemAlloc, but returns NULL if out of space, rather than erroring.*/void *ShmemAllocNoError(Size size){Size newStart;Size newFree;void *newSpace;/** Ensure all space is adequately aligned. We used to only MAXALIGN this* space but experience has proved that on modern systems that is not good* enough. Many parts of the system are very sensitive to critical data* structures getting split across cache line boundaries. To avoid that,* attempt to align the beginning of the allocation to a cache line* boundary. The calling code will still need to be careful about how it* uses the allocated space - e.g. by padding each element in an array of* structures out to a power-of-two size - but without this, even that* won't be sufficient.*/size = CACHELINEALIGN(size);Assert(ShmemSegHdr != NULL);SpinLockAcquire(ShmemLock);newStart = ShmemSegHdr->freeoffset;newFree = newStart + size;if (newFree <= ShmemSegHdr->totalsize){newSpace = (void *) ((char *) ShmemBase + newStart);ShmemSegHdr->freeoffset = newFree;}elsenewSpace = NULL;SpinLockRelease(ShmemLock);/* note this assert is okay with newSpace == NULL */Assert(newSpace == (void *) CACHELINEALIGN(newSpace));return newSpace;}
参考
https://www.postgresql.org/about/featurematrix/detail/240/
文章转载自CP的PostgreSQL厨房,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




