PostgreSQL在shutdown时会进行checkpoint。其流程如下:
1、在主进程中,会首先注册一个信号处理函数reaper,用于向checkpoint等子进程发送信号。向checkpoint进程发送SIGUSR2信号
PostmasterMain(int argc, char *argv[])
pqsignal_no_restart(SIGCHLD, reaper); /* handle child termination */
reaper:
while ((pid = waitpid(-1, &exitstatus, WNOHANG)) > 0){
...
if (pid == CheckpointerPID){
...
SignalChildren(SIGUSR2);//向checkpoint进程发送SIGUSR2信号
}
...
}
2、checkpoint进程,也会注册一个信号处理函数ReqShutdownHandler,用于处理主进程发送过来的SIGUSR2信号。接收到该信号后将shutdown_requested置为TRUE。在checkpoint进程的for循环中,如果shutdown_requested为TRUE,则进入shutdown流程:stop每个sender进程,所有sender进程stop后,根据条件进行checkpoint:CreateRestartPoint后者CreateCheckPoint:
CheckpointerMain(void)->
//为信号SIGUSR2安装信号处理函数ReqShutdownHandler
pqsignal(SIGUSR2, ReqShutdownHandler); /* request shutdown */
...
for (;;){
if (shutdown_requested){
/* Close down the database */
ShutdownXLOG(0, 0);
|-- WalSndInitStopping();//向每个sender进程发送信号修改到stopping状态
| WalSndWaitStopping();
| if (RecoveryInProgress())
| CreateRestartPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE);
| else{
| if (XLogArchivingActive() && XLogArchiveCommandSet())
| RequestXLogSwitch(false);
| CreateCheckPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE);
| }
|-- ...
proc_exit(0);
}
...
checkpoint
}
3、ReqShutdownHandler函数将shutdown_requested置为TRUE:
/* SIGUSR2: set flag to run a shutdown checkpoint and exit */
static void
ReqShutdownHandler(SIGNAL_ARGS)
{
shutdown_requested = true;
SetLatch(MyLatch);
}