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)

相关推荐
达梦数据7 小时前
达梦数据复制软件DMDRS搭建部署示例:源数据库DM8到目标数据库DM8一对一数据同步
数据库
IT_Octopus8 小时前
从一个应用开发者的角度,搞懂大数据查询的完整链路
java·大数据·数据库
Htr_8 小时前
Creem 2.0 使用指南:面向 AI 构建时代的资金平台
android·数据库·人工智能·ui·photoshop
我是大猴子8 小时前
reids的数据结构的应用场景
数据库
螺蛳粉 螺蛳粉8 小时前
mysql的备份与恢复
linux·运维·数据库·mysql
艾醒(AiXing-w)9 小时前
LangChain 1.0 智能体开发(三):Agent 记忆管理——从短期对话到跨会话长期记忆
数据库·人工智能·langchain
MSTcheng.9 小时前
KES 进了 K8s 之后运维归谁管?
数据库
知识的搬运工旺仔9 小时前
CREATE INDEX CONCURRENTLY:线上建索引不阻塞 DML 的代价与坑
数据库·后端·sql
guo_wen_qiang10 小时前
mysql中有哪些日志
数据库·mysql