🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# Chapter 45\. 后台工作进程 PostgreSQL可以扩展在分立的进程中运行用户提供的代码。 命令`postgres`启动, 停止和监控这些进程,允许它们的生命周期与服务器状态紧密关联。这些进程可以选择连接 PostgreSQL的共享内存并与数据库内部连接;它们也可以串行地运行多个事务,就像 常规的客户端连接的服务器进程。另外,通过链接到libpq,它们可以连接到服务器并 且和常规的客户端应用表现一样。 | **Warning** | |:--- | | 使用后台工作进程有着相当大的牢固和安全风险。这是因为它们是用C语言写的,有着不受限制的数据 访问方式。乐于使用包含后台工作进程的模块的管理员们应当极度地当心。只有仔细审计过的模块才 应该被允许运行后台工作进程。 | 只有`shared_preload_libraries`里列出的模块能够运行后台工作进程。想要运行后台工作 程序的模块需要通过从它的`_PG_init()`调用 `RegisterBackgroundWorker(`BackgroundWorker *worker`)`来注册 这个程序。`BackgroundWorker`结构是这样定义的: ``` typedef void (*bgworker_main_type)(void *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`是当进程被启动时指向所运行函数的一个指针。该函数必须使 用`void *`类型的单一参数并返回`void`类型的值。 `bgw_main_arg`将作为唯一参数被传递给此函数。注意全局变量 `MyBgworkerEntry`指向进程注册时传递的 `BackgroundWorker`结构的一份拷贝。 进程一旦运行,就可以通过调用 `BackgroundWorkerInitializeConnection(`char *dbname`, `char *username`)` 连接到一个数据库。这样进程可以使用`SPI`接口运行事务和查询。如果 `dbname`值为NULL,会话不被连接到任何特定数据库,但是可以获取共享的目录。如果 `username`值为NULL,进程会以`initdb`运行时创建的超级用户身份来运行。 每个后台进程只能调用一次BackgroundWorkerInitializeConnection,它不能切换数据库。 Signals are initially blocked when control reaches the 控制`bgw_main`函数开始锁定信号,并且必须由此函数解锁;这样在必要时可以允许 进程定制它的信号处理程序。通过调用`BackgroundWorkerUnblockSignals`可以在新进程 中为信号解锁,通过调用`BackgroundWorkerBlockSignals`可以加锁。 后台工作程序是被预期连续运行的;如果它们干净的退出了,`postgres`会立即重启它们。 当它们无事可做时,考虑进入可中断的睡眠;通过调用`WaitLatch()`可以实现这 一点。调用该函数时确定`WL_POSTMASTER_DEATH`标志被设置,并且在`postgres` 自身终止的紧急情况下为提示的退出验证返回码。 `worker_spi` contrib模块包含一个展示一些有用技术的范例。