1先上个图,看一下函数调用过程梗概,中间略过部分细节@H_502_4@
@H_502_4@
初始化walsender和walreceiver相关结构方法调用流程图@H_502_4@
@H_502_4@
2初始化xlog相关结构@H_502_4@
话说main()->…->PostmasterMain()->…->reset_shared() ->CreateSharedMemoryAndSemaphores()>…->WalSndShmemInit(),调用ShmemInitStruct(),在其中调用hash_search()在哈希表索引@H_502_4@"ShmemIndex"@H_502_4@中查找@H_502_4@"Wal Sender Ctl"@H_502_4@,如果没有,就在shmemIndex中给@H_502_4@"Wal Sender Ctl"@H_502_4@分一个HashElement和ShmemIndexEnt(entry),在其中的Entry中写上@H_502_4@"WalSender Ctl"@H_502_4@。返回ShmemInitStruct(),再调用ShmemAlloc()在共享内存上给@H_502_4@"WalSender Ctl"@H_502_4@相关结构(见下面“@H_502_4@Wal Sender Ctl@H_502_4@和@H_502_4@Wal Receiver Ctl@H_502_4@相关结构图”)分配空间,设置entry(在这儿及ShmemIndexEnt类型变量)的成员location指向该空间,size成员记录该空间大小,最后返回WalSndShmemInit(),让WalSndCtlData*类型全局变量WalSndCtl指向所分配内存,初始化WalSndCtlData结构类型的成员值。@H_502_4@
接着WalRcvShmemInit()-> ShmemInitStruct(),在其中调用hash_search()在哈希表索引@H_502_4@"ShmemIndex"@H_502_4@中查找@H_502_4@"Wal Receiver Ctl"@H_502_4@,如果没有,就在shmemIndex中给@H_502_4@"Wal Receiver Ctl"@H_502_4@分一个HashElement和ShmemIndexEnt(entry),在其中的Entry中写上@H_502_4@"WalReceiver Ctl"@H_502_4@。返回ShmemInitStruct(),再调用ShmemAlloc()在共享内存上给@H_502_4@"WalReceiver Ctl"@H_502_4@相关结构(见下面“@H_502_4@Wal Sender Ctl@H_502_4@和@H_502_4@Wal Receiver Ctl@H_502_4@相关结构图”)分配空间,设置entry(在这儿及ShmemIndexEnt类型变量)的成员location指向该空间,size成员记录该空间大小,最后返回WalRcvShmemInit(),让WalRcvData*类型全局变量WalRcv指向所分配内存,初始化WalRcvData结构类型的成员值。@H_502_4@
@H_502_4@
相关结构定义和图见下面:@H_502_4@
typedef enum WalSndState@H_502_4@
{@H_502_4@
WALSNDSTATE_STARTUP = 0,@H_502_4@
WALSNDSTATE_BACKUP,@H_502_4@
WALSNDSTATE_CATCHUP,@H_502_4@
WALSNDSTATE_STREAMING@H_502_4@
} WalSndState;@H_502_4@
@H_502_4@
/*@H_502_4@
* Each walsender has a WalSnd structin shared memory.@H_502_4@
*/@H_502_4@
typedef struct WalSnd@H_502_4@
{@H_502_4@
pid_t pid; /* this walsender's process id,or 0 */@H_502_4@
WalSndState state; /* this walsender's state */@H_502_4@
XLogRecPtr sentPtr; /* WAL has been sent up to this point */@H_502_4@
@H_502_4@
/*@H_502_4@
* The xloglocations that have been written,flushed,and applied by@H_502_4@
* standby-side. These maybe invalid if the standby-side has not offered@H_502_4@
* values yet.@H_502_4@
*/@H_502_4@
XLogRecPtr write;@H_502_4@
XLogRecPtr flush;@H_502_4@
XLogRecPtr apply;@H_502_4@
@H_502_4@
/* Protects shared variables shown above.*/@H_502_4@
slock_t mutex;@H_502_4@
@H_502_4@
/*@H_502_4@
* Latch used by backendsto wake up this walsender when it has work to@H_502_4@
* do.@H_502_4@
*/@H_502_4@
Latch latch;@H_502_4@
@H_502_4@
/*@H_502_4@
* The priority order ofthe standby managed by this WALSender,as listed@H_502_4@
* insynchronous_standby_names,or 0 if not-listed. Protected by@H_502_4@
* SyncRepLock.@H_502_4@
*/@H_502_4@
int sync_standby_priority;@H_502_4@
} WalSnd;@H_502_4@
@H_502_4@
extern WalSnd *MyWalSnd;@H_502_4@
@H_502_4@
/* There is one WalSndCtl structfor the whole database cluster */@H_502_4@
typedef struct@H_502_4@
{@H_502_4@
/*@H_502_4@
* Synchronous replicationqueue. Protected by SyncRepLock.@H_502_4@
*/@H_502_4@
SHM_QUEUE SyncRepQueue;@H_502_4@
@H_502_4@
/*@H_502_4@
* Current location of thehead of the queue. All waiters should have a@H_502_4@
* waitLSN that followsthis value. Protected by SyncRepLock.@H_502_4@
*/@H_502_4@
XLogRecPtr lsn;@H_502_4@
@H_502_4@
/*@H_502_4@
* Are any sync standbysdefined? Waiting backends can'treload the@H_502_4@
* config filesafely,so WAL writer updates this value as needed.@H_502_4@
* Protected bySyncRepLock.@H_502_4@
*/@H_502_4@
bool sync_standbys_defined;@H_502_4@
@H_502_4@
WalSnd walsnds[1]; /* VARIABLE LENGTH ARRAY */@H_502_4@
} WalSndCtlData;@H_502_4@
@H_502_4@
extern WalSndCtlData *WalSndCtl;@H_502_4@
@H_502_4@
typedef enum@H_502_4@
{@H_502_4@
WALRCV_STOPPED,/* stopped and mustn't start up again */@H_502_4@
WALRCV_STARTING,/* launched,but the process hasn't@H_502_4@
*initialized yet */@H_502_4@
WALRCV_RUNNING,/* walreceiver is running */@H_502_4@
WALRCV_STOPPING /* requested to stop,but still running */@H_502_4@
} WalRcvState;@H_502_4@
@H_502_4@
/* Shared memory area formanagement of walreceiver process */@H_502_4@
typedef struct@H_502_4@
{@H_502_4@
/*@H_502_4@
* PID of currently active walreceiverprocess,its current state and@H_502_4@
* start time (actually,the time at which it was requested to be@H_502_4@
* started).@H_502_4@
*/@H_502_4@
pid_t pid;@H_502_4@
WalRcvState walRcvState;@H_502_4@
pg_time_t startTime;@H_502_4@
@H_502_4@
/*@H_502_4@
* receiveStart is thefirst byte position that will be received. When@H_502_4@
* startup process startsthe walreceiver,it sets receiveStart to the@H_502_4@
* point where it wants thestreaming to begin.@H_502_4@
*/@H_502_4@
XLogRecPtr receiveStart;@H_502_4@
@H_502_4@
/*@H_502_4@
* receivedUpto-1 is thelast byte position that has already been@H_502_4@
* received. At the first startup of walreceiver,receivedUpto is set to@H_502_4@
* receiveStart. Afterthat,walreceiver updates this whenever it flushes@H_502_4@
* the received WAL todisk.@H_502_4@
*/@H_502_4@
XLogRecPtr receivedUpto;@H_502_4@
@H_502_4@
/*@H_502_4@
* latestChunkStart is thestarting byte position of the current "batch"@H_502_4@
* of received WAL. It's actually the same as the prevIoUs valueof@H_502_4@
* receivedUpto before thelast flush to disk. Startup process canuse@H_502_4@
* this to detect whetherit's keeping up or not.@H_502_4@
*/@H_502_4@
XLogRecPtr latestChunkStart;@H_502_4@
@H_502_4@
/*@H_502_4@
* connection string; isused for walreceiver to connect with the primary.@H_502_4@
*/@H_502_4@
char conninfo[MAXCONNINFO];@H_502_4@
@H_502_4@
slock_t mutex; /* locks shared variables shown above */@H_502_4@
} WalRcvData;@H_502_4@
@H_502_4@
extern WalRcvData *WalRcv;@H_502_4@
@H_502_4@
@H_502_4@
初始化完@H_502_4@Wal Receiver Ctl@H_502_4@和@H_502_4@Wal Receiver Ctl@H_502_4@相关结构的共享内存结构图@H_502_4@
为了精简上图,把创建shmem的哈希表索引@H_502_4@"ShmemIndex"@H_502_4@时创建的HCTL结构删掉了,这个结构的作用是记录创建可扩展哈希表的相关信息,不过这个结构在@H_502_4@"ShmemIndex"@H_502_4@创建完成后也会由于出了对象作用域而消失。增加了左边灰色底的部分,描述共享内存@H_502_4@/shmem@H_502_4@里各变量物理布局概览,由下往上,由低地址到高地址。图中黄色的索引项就是本节新增加的索引项。@H_502_4@
@H_502_4@
@H_502_4@
Wal Sender Ctl@H_502_4@和@H_502_4@Wal Receiver Ctl@H_502_4@相关结构图@H_502_4@
原文链接:https://www.f2er.com/postgresql/196636.html