openGauss postmaster退出流程

Postmaster 关机退出流程与状态变化

一、全局状态变量

volatile PMState pmState = PM_INIT; // 当前 PM 状态

volatile int Shutdown = NoShutdown; // 关机请求级别

Shutdown 级别(由信号设置):

  • NoShutdown = 0

  • SmartShutdown = 1(SIGTERM,等事务结束)

  • FastShutdown = 2(SIGINT,立即回滚事务)

  • ImmediateShutdown = 3(SIGQUIT,直接退出)

PMState 状态机序列(正常关机):

PM_RUN → PM_WAIT_BACKENDS → PM_SHUTDOWN → PM_SHUTDOWN_2 → PM_WAIT_DEAD_END → PM_NO_CHILDREN → ExitPostmaster(0)


二、三种关机模式的入口

  1. Smart Shutdown (SIGTERM) --- 仅主库在 standby mode 时

postmaster.cpp:6488-6505

  • 设置 g_instance.status = SmartShutdown

  • 调用 pgaudit_system_stop_ok(SmartShutdown)

  • 如果 pmState == PM_STARTUP || PM_INIT → 立即 ExitPostmaster(0)(还没起来)

  • 否则继续后续流程

  1. Fast Shutdown (SIGINT / non-standby SIGTERM)

postmaster.cpp:6506-6521

  • 设置 g_instance.status = FastShutdown

  • 调用 pgaudit_system_stop_ok(FastShutdown)

  • 如果 pmState == PM_STARTUP || PM_INIT → 立即 ExitPostmaster(0)

  • 否则继续后续流程

  1. Immediate Shutdown (SIGQUIT)

postmaster.cpp:6789-6809

  • 设置 g_instance.status = ImmediateShutdown

  • 调用 KillGraceThreads() → 发送 SIGQUIT 给 AlarmCheckerPID

  • 调用 ExitPostmaster(0) --- 直接退出,不等待任何子进程


三、Fast/Smart Shutdown 详细流程(主线)

收到信号后进入 pmdie() 的主流程(postmaster.cpp:6527-6787):

阶段 1:终止各类进程

A. 如果在 PM_RECOVERY 状态:

// postmaster.cpp:6733-6747

if (ENABLE_THREAD_POOL) g_threadPoolControler->ShutDownThreads();

if (pmState == PM_RECOVERY) {

pmState = PM_WAIT_BACKENDS; // 直接进入等待

}

B. 如果在 PM_RUN / PM_HOT_STANDBY / PM_WAIT_BACKUP / PM_WAIT_READONLY / PM_WAIT_BACKENDS 状态:

// postmaster.cpp:6748-6777

ereport(LOG, (errmsg("aborting any active transactions")));

// 1. 关闭线程池

if (ENABLE_THREAD_POOL) {

g_threadPoolControler->CloseAllSessions();

g_threadPoolControler->ShutDownScheduler(true, true);

g_threadPoolControler->ShutDownThreads();

}

// 2. 发送 SIGTERM 给所有普通后端和 autovacuum worker

SignalSomeChildren(SIGTERM, BACKEND_TYPE_NORMAL | BACKEND_TYPE_AUTOVAC);

// 3. 关闭所有 background worker

ShutdownAllBgWorker();

// 4. 发送 SIGTERM 给特殊子进程

signal_child(AutoVacPID, SIGTERM); // autovac launcher

signal_child(PgJobSchdPID, SIGTERM); // job scheduler

signal_child(WalWriterPID, SIGTERM); // WAL writer

signal_child(WalWriterAuxiliaryPID, SIGTERM);

pmState = PM_WAIT_BACKENDS;

C. 发送信号后的关键逻辑:

PostmasterStateMachine(); // 尝试推进状态机


四、PostmasterStateMachine 状态机推进

核心函数:PostmasterStateMachine() --- postmaster.cpp:9197

状态 1: PM_WAIT_BACKENDS → 等所有后端退出

// 条件检查:所有子进程都退出了

if (CountChildren(BACKEND_TYPE_NORMAL | BACKEND_TYPE_AUTOVAC) == 0 &&

StartupPID == 0 && TwoPhaseCleanerPID == 0 && FaultMonitorPID == 0 &&

WalReceiverPID == 0 && WalRcvWriterPID == 0 && DataReceiverPID == 0 &&

DataRcvWriterPID == 0 && BgWriterPID == 0 && WalWriterPID == 0 &&

WalWriterAuxiliaryPID == 0 && AutoVacPID == 0 && SpBgWriterPID == 0 &&

WLMCollectPID == 0 && WLMMonitorPID == 0 && WLMArbiterPID == 0 &&

CPMonitorPID == 0 && PgJobSchdPID == 0 && CBMWriterPID == 0 &&

TxnSnapCapturerPID == 0 && RbCleanrPID == 0 && SnapshotPID == 0 &&

AshPID == 0 && CsnminSyncPID == 0 && StackPerfPID == 0 &&

CfsShrinkerPID == 0 && rackMemCleanerPID == 0 &&

BarrierCreatorPID == 0 && PageRepairPID == 0 && BarrierPreParsePID == 0 &&

SqlLimitPID == 0 && UndoLauncherPID == 0 && UndoRecyclerPID == 0 &&

GlobalStatsPID == 0 && IsAllPageWorkerExit() && IsAllBuildSenderExit())

当条件满足且 !g_instance.fatal_error:

// postmaster.cpp:9273-9347

// 1. 启动 checkpointer(如果没运行)

if (CheckpointerPID == 0) initialize_util_thread(CHECKPOINT_THREAD);

// 2. 停止 page writer

ckpt_cxt_ctl->page_writer_can_exit = false;

for (各 PageWriterPID) signal_child(SIGTERM);

WaitUntilPagewriterReceiveSigterm();

// 3. 等待 logical walsender 进入 stopping 状态

SigtermWalsenderToStoppingState();

WaitUntilWalsenderReceiveSigterm();

// 4. 通知 checkpointer 做 shutdown checkpoint

signal_child(CheckpointerPID, SIGUSR2);

pmState = PM_SHUTDOWN; // ← 关键状态跳转

状态 2: PM_SHUTDOWN → 等 Checkpointer 退出

在 reaper() 中(postmaster.cpp:7882-7914):

if (pid == CheckpointerPID && EXIT_STATUS_0(exitstatus) && pmState == PM_SHUTDOWN) {

CheckpointerPID = 0;

// 如果有 shared storage xlog copy thread

if (sharedStorageXlogCopyThreadPID != 0)

signal_child(sharedStorageXlogCopyThreadPID, SIGTERM);

// ...

}

Checkpointer 收到 SIGUSR2 后执行 shutdown checkpoint:

  • 调用 CreateRestartPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE)

  • 刷脏页到磁盘

  • 写入 checkpoint record 到 WAL

  • 退出(exit 0)

状态 3: PM_SHUTDOWN_2 → 等 archiver 和 walsender 退出

// postmaster.cpp:9358-9378

if (pmState == PM_SHUTDOWN_2) {

if (PgArchPID == 0 && CountChildren(BACKEND_TYPE_ALL) == 0 &&

WalReceiverPID == 0 && WalRcvWriterPID == 0 &&

DataReceiverPID == 0 && DataRcvWriterPID == 0 &&

ObsArchAllShutDown() && HeartbeatPID == 0 &&

sharedStorageXlogCopyThreadPID == 0) {

pmState = PM_WAIT_DEAD_END;

}

}

PM_SHUTDOWN_2 的触发(checkpointer 退出后):

// 在 reaper 中,checkpointer 退出后会进一步处理

pmState = PM_SHUTDOWN_2;

// 发送 SIGTERM 给 archiver 和 walsender

signal_child(PgArchPID, SIGTERM);

signal_child(WalReceiverPID, SIGUSR2); // 通知 walsender 发送剩余 WAL

状态 4: PM_WAIT_DEAD_END → 等 dead_end 子进程退出

// postmaster.cpp:9380-9404

if (pmState == PM_WAIT_DEAD_END) {

if (DLGetHead(backend_list) == NULL && PgArchPID == 0 &&

AuditAllShutDown() && ckpt_all_flush_buffer_thread_exit() &&

ObsArchAllShutDown() && !SS_PERFORMING_SWITCHOVER) {

AsssertAllChildThreadExit();

pmState = PM_NO_CHILDREN;

}

}

状态 5: PM_NO_CHILDREN → ExitPostmaster

// postmaster.cpp:9418-9438

if (g_instance.status > NoShutdown && pmState == PM_NO_CHILDREN) {

if (g_instance.fatal_error) {

ereport(LOG, (errmsg("abnormal database system shutdown")));

ExitPostmaster(1);

} else {

if (t_thrd.postmaster_cxt.ReachedNormalRunning)

CancelBackup(); // 取消 exclusive backup 模式

ExitPostmaster(0); // ← 正常退出

}

}


五、各子进程退出行为

进程 接收信号 退出行为
Backend (普通) SIGTERM 回滚活跃事务,优雅退出
Autovacuum Worker SIGTERM 停止 vacuume,优雅退出
AutoVac Launcher SIGTERM 停止 launcher,退出
WalWriter SIGTERM 完成当前 WAL 写入,退出
BgWriter SIGTERM 完成刷脏,退出
Checkpointer SIGUSR2 (shutdown) 执行 shutdown checkpoint,退出
WalSender SIGUSR2 发送剩余 WAL,等待同步,退出
PgArch (归档) SIGTERM 完成当前归档,退出
SysLogger SIGUSR1 (flush) 刷新日志缓冲,退出
WalReceiver SIGTERM 断开复制连接,退出
DataReceiver SIGTERM 断开数据接收,退出
PageWriter SIGTERM 完成页面写入,退出

六、Shutdown 级别对比

特性 Smart (SIGTERM) Fast (SIGINT) Immediate (SIGQUIT)
等事务结束
写 shutdown checkpoint
等子进程退出
下次启动需 recovery 可能(快关可能丢未刷数据)
数据一致性 最佳 可能不一致
适用场景 计划停机 紧急停止 卡死/崩溃恢复

七、流程图总结

收到信号

├─ SIGQUIT → ImmediateShutdown → KillGraceThreads → ExitPostmaster(0) 【直接退出】

├─ SIGTERM (standby) → SmartShutdown

└─ SIGTERM/SIGINT (其他) → FastShutdown

├─ PM_STARTUP/PM_INIT → ExitPostmaster(0) 【还没起来,直接退】

└─ PM_RUN/PM_RECOVERY/PM_HOT_STANDBY

├─ 关闭 ThreadPool (CloseAllSessions + ShutDownThreads)

├─ SIGTERM → 所有 Backend + Autovac

├─ ShutdownAllBgWorker()

├─ SIGTERM → AutoVac, PgJobSchd, WalWriter

PM_WAIT_BACKENDS

│ 等所有后端退出 (CountChildren == 0)

启动/唤醒 Checkpointer

SIGTERM → PageWriter

SIGTERM → Logical WalSender (等进入 stopping)

SIGUSR2 → Checkpointer (做 shutdown checkpoint)

PM_SHUTDOWN

│ 等 Checkpointer 退出 (exit 0)

PM_SHUTDOWN_2

│ 发 SIGTERM → Archiver, Walsender

│ 等所有非 syslogger 子进程退出

PM_WAIT_DEAD_END

│ 等 backend_list 为空 + Archiver 退出

PM_NO_CHILDREN

ExitPostmaster(0) ← 正常退出

ExitPostmaster(1) ← 异常退出 (fatal_error)

相关推荐
叫我:松哥1 小时前
基于flask仿小米商城管理系统,使用flask开的一个商场网站
数据库·后端·python·flask
子非鱼a1 小时前
【WEB】[BJDCTF2020]Easy MD5
数据库
APItesterCris1 小时前
告别人工盯品:借助 OpenClaw 搭建商品自动监控与数据分析系统(完整实操)
大数据·数据库·数据仓库·自动化
zcn1261 小时前
exists子查询改写思考
数据库·sql·sql优化改写
betazhou2 小时前
mysql shell8.4.10+mysql 8.4.10搭建MySQL replicaset主从
数据库·mysql·ffmpeg·replicaset·mysql shell
zcmodeltech2 小时前
反应装置模型控制系统设计与实现:多设备协同联动方案
java·网络·数据库·stm32·嵌入式硬件·能源·制造
Elastic 中国社区官方博客2 小时前
从建议到修复的 4 个阶段:使用 Elastic Workflows 实现人在回路中的自动化
运维·数据库·人工智能·后端·elasticsearch·ai·自动化
北京靠谱的GEO优化机构2 小时前
海外推广:没有媒体内容,SEO就是“无米之炊“
服务器·数据库·媒体
2601_962071572 小时前
数据库系统架构与DBMS功能探微:现代信息时代数据管理的关键
java·开发语言·数据库