数据库是典型的多进程(或者多线程)的架构,进程之间要频繁的通讯,传递信息。共享内存是速度最快的进程间传递信息的方式。Oracle, PostgreSQL的核心内存组件就是一块共享内存,这块共享内存在Oracle数据库世界中被叫做SGA(System Global Area),在PG的世界中就叫做共享内存。
在Linux/Unix操作系统中实现共享内存有三种技术:System V,POSIX和mmap方式。PG只使用System V和mmap两种方式,不使用POSIX方式。相关的参数有shared_memory_type和huge_pages两个参数。Huge Page是一个常考的技术要点,希望童鞋们空闲时仔细研究一下这个问题,以后我也会发帖介绍。
现代Linux操作系统推荐使用匿名mmap方式,这也是PG使用的方式。但是System V共享内存有一个独有的特性是mmap所不具备的,就是当一个进程贴(attach)到一块共享内存后,它能够知道此时此刻有多少个进程正在使用这块共享内存。这个信息是通过shmctl()指定IPC_STAT参数,从shmid_ds结构的shm_nattch这个字段获得的。
这个功能是PG所需要的,为此,Robert Haas提供了一个补丁,利用了System V和mmap两种共享内存技术,取其所长,避其所短,具体细节可以参考他的一篇博客:
https://rhaas.blogspot.com/2012/06/absurd-shared-memory-limits.html
当Postmaster主进程启动后,在它创建任何子进程之前会调用CreateSharedMemoryAndSemaphores()函数创建共享内存。这个函数进一步调用PGSharedMemoryCreate()进行共享内存的创建。
共享内存的尺寸计算和创建,都是在任何子进程诞生之前完成的,所以只要你修改的参数改变了共享内存的尺寸,就需要重新数据库实例才能让你的修改生效。