↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3
历史版本。 PostgreSQL 9.3 已结束支持。 2018-11-08. 请参阅 当前版本手册.

第 45 章 后台工作进程

PostgreSQL 可以扩展为在独立进程中运行用户提供的代码。这样的进程由 postgres 启动、停止和监控,这使得它们的生命周期与服务器状态紧密关联。这些进程可以选择附加到 PostgreSQL 的共享内存区域并从内部连接到数据库;它们也可以像常规的客户端连接服务器进程一样串行运行多个事务。此外,通过链接到 libpq,它们可以连接到服务器并且表现得像常规客户端应用一样。

警告

使用后台工作进程存在相当大的健壮性和安全风险,因为它们是用 C 语言编写的,可以不受限制地访问数据。希望启用包含后台工作进程的管理员应当极度谨慎。只应允许经过仔细审计的模块运行后台工作进程。

只有 shared_preload_libraries 中列出的模块才能运行后台工作进程。想要运行后台工作进程的模块需要通过在其 _PG_init() 中调用 RegisterBackgroundWorker(BackgroundWorker *worker) 来注册它。结构 BackgroundWorker 的定义如下:

typedef void (*bgworker_main_type)(Datum main_arg);
typedef struct BackgroundWorker
{
    char        bgw_name[BGW_MAXLEN];
    int         bgw_flags;
    BgWorkerStartTime bgw_start_time;
    int         bgw_restart_time;       /* in seconds, or BGW_NEVER_RESTART */
    bgworker_main_type bgw_main;
    Datum       bgw_main_arg;
} BackgroundWorker;

bgw_name 是用于日志消息、进程列表等类似场合的字符串。

bgw_flags 是一个按位或的位掩码,指示模块想要的能力。可能的取值有 BGWORKER_SHMEM_ACCESS(请求共享内存访问)和 BGWORKER_BACKEND_DATABASE_CONNECTION(请求建立数据库连接的能力,通过该连接之后可以运行事务和查询)。使用 BGWORKER_BACKEND_DATABASE_CONNECTION 连接数据库的后台工作进程还必须使用 BGWORKER_SHMEM_ACCESS 附加共享内存,否则工作进程启动将失败。

bgw_start_time 是 postgres 应当启动该进程时服务器所处的状态;它可以是 BgWorkerStart_PostmasterStart(一旦 postgres 自身完成初始化就启动;请求此值的进程不能建立数据库连接)、BgWorkerStart_ConsistentState(一旦热备中达到一致状态就启动,允许进程连接到数据库并运行只读查询)或 BgWorkerStart_RecoveryFinished(一旦系统进入正常的读-写状态就启动)。注意,在不是热备的服务器中,后两个值是等效的。还要注意,此设置只指示进程何时被启动;当达到其他状态时它们并不会停止。

bgw_restart_time 是进程崩溃时 postgres 重启该进程之前应等待的间隔(以秒计)。它可以是任意正值,或者 BGW_NEVER_RESTART(表示崩溃时不重启进程)。

bgw_main 是指向进程启动时要运行的函数的指针。该函数必须接受一个 Datum 类型的参数并返回 void。bgw_main_arg 将作为其唯一参数传递给它。注意,全局变量 MyBgworkerEntry 指向注册时传递的 BackgroundWorker 结构的一份副本。

运行起来之后,进程可以通过调用 BackgroundWorkerInitializeConnection(char *dbname, char *username) 连接到数据库。这允许进程使用 SPI 接口运行事务和查询。如果 dbname 为 NULL,会话不会连接到任何特定数据库,但可以访问共享目录。如果 username 为 NULL,进程将以 initdb 期间创建的超级用户身份运行。BackgroundWorkerInitializeConnection 在每个后台进程中只能调用一次,无法切换数据库。

当控制到达 bgw_main 函数时信号最初是被阻塞的,必须由该函数解除阻塞;这是为了让进程在必要时自定义其信号处理器。在新进程中可以通过调用 BackgroundWorkerUnblockSignals 解除信号阻塞,通过调用 BackgroundWorkerBlockSignals 阻塞信号。

后台工作进程应当持续运行;如果它们干净地退出,postgres 会立即重启它们。在无事可做时可以考虑做可中断的睡眠;这可以通过调用 WaitLatch() 实现。确保调用该函数时设置了 WL_POSTMASTER_DEATH 标志,并在 postgres 自身已终止的紧急情况下检查返回码以便及时退出。

worker_spi contrib 模块包含一个可以工作的示例,它演示了一些有用的技巧。

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.