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模块包含一个展示一些有用技术的范例。