这一节 pg 初始化堆扫描同步支持用到的相关结构。
堆扫描同步是当多个进程在同一个表上做顺序扫描( sequential scan ), pg 尝试保持他们同步以减少整体 I/O 需求。这个目标是读每一个页到共享内存仅一次,且使所有参与扫描这个页的进程在这个页被替换出共享内存前处理这个页。
活跃 backend 进程列表,这被用来跟踪 pg 有多少个孩子和在需要的时候给他们发送信号。
1 先上个图,看一下函数调用过程梗概,中间略过部分细节
初始化同步扫描和 Backend 结构数组方法调用流程图
2 初始化同步扫描相关结构
话说 main()-> … ->PostmasterMain()-> … ->reset_shared() -> CreateSharedMemoryAndSemaphores()>…-> SyncScanShmemInit () ,调用 ShmemInitStruct() , 在其中 调用 hash_search() 在哈希表索引 "ShmemIndex" 中查找 " Sync Scan Locations List " ,如果没有,就在 shmemIndex 中给 " Sync Scan Locations List " 分一个 HashElement 和 ShmemIndexEnt ( entry ) ,在其中的 Entry 中写上 " Sync Scan Locations List " 。返回 ShmemInitStruct() ,再调用 ShmemAlloc() 在共享内存上给 " Sync Scan Locations List " 相关结构(见下面“ Sync Scan Locations List 相关结构图” )分配空间,设置 entry (在这儿及ShmemIndexEnt 类型变量)的成员 location 指向该空间, size 成员记录该空间大小 , 最后返回 SyncScanShmemInit () ,让 ss_scan_locations_t * 类型静态 全局变量 scan_locations 指向 所分配内存 ,初始化 ss_scan_locations_t 结构类型的成员值。
接着 main()-> … ->PostmasterMain()-> … ->reset_shared() -> CreateSharedMemoryAndSemaphores() ->…-> ShmemBackendArrayAllocation () , 调用 ShmemAlloc() 在共享内存上分配 2 * MaxBackends 个 Backend 结构数组 见下面“ Backend 结构数组图” ) , 让 Backend * 类型静态 全局变量 ShmemBackendArray 指向 所分配内存 ,用memset 把所分配内存置0 。
相关结构定义和图见下面:
typedef struct ss_scan_location_t
{
RelFileNode relfilenode ; /* identity of a relation */
BlockNumber location ; /* last-reported location in the relation */
} ss_scan_location_t ;
typedef struct ss_lru_item_t
{
struct ss_lru_item_t * prev ;
struct ss_lru_item_t * next ;
ss_scan_location_t location ;
} ss_lru_item_t ;
typedef struct ss_scan_locations_t
{
ss_lru_item_t * head ;
ss_lru_item_t * tail ;
ss_lru_item_t items [1]; /* SYNC_SCAN_NELEM items */
} ss_scan_locations_t ;
#define SizeOfScanLocations (N) offsetof(ss_scan_locations_t, items[N])
/* Pointer to struct in shared memory */
static ss_scan_locations_t *scan_locations;
/* prototypes for internal functions */
static BlockNumber ss_search ( RelFileNode relfilenode,
BlockNumber location, bool set);
typedef struct bkend
{
pid_t pid; /* process id of backend */
long cancel_key; /* cancel key for cancels for this backend */
int child_slot; /* PMChildSlot for this backend, if any */
bool is_autovacuum; /* is it an autovacuum process? */
bool dead_end; /* is it going to send an error and quit? */
Dlelem elem; /* list link in BackendList */
} Backend;
static Backend *ShmemBackendArray;
初始化完 Sync Scan Locations List 相关结构 的共享内存结构图
为了精简上图,把创建 shmem 的哈希表索引 "ShmemIndex" 时创建的 HCTL 结构删掉了,这个结构的作用是记录创建可扩展哈希表的相关信息,不过这个结构在 "ShmemIndex" 创建完成后也会由于出了对象作用域而消失。增加了左边灰色底的部分,描述 共享内存 /shmem 里各变量物理布局概览,由下往上,由低地址到高地址。 图中黄色的索引项就是本节新增加的索引项。
Sync Scan Locations List 相关结构图
Backend 结构数组图