选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3
历史版本PostgreSQL 9.3 已于 2018 年 11 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本

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

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

bgw_main 是指向进程启动时要运行的函数的指针。该函数必须接受一个 Datum 类型的参数并返回 voidbgw_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 模块包含一个可以工作的示例,它演示了一些有用的技巧。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。