后台工作进程
可以扩展Greenplum数据库以在单独的进程中运行用户提供的代码。
这些进程由postgres
启动,停止和监视,这使得它们的生命周期与服务器的状态紧密相关。
这些进程可以选择连接到Greenplum数据库的共享内存区域并在内部连接到数据库; 它们还可以串行运行多个事务,就像常规的客户端连接服务器进程一样。
此外,通过链接到libpq
,它们可以连接到服务器,并且行为类似于常规客户端应用程序。
Warning: 使用后台工作进程存在相当大的稳健性和安全性风险,因为使用C
语言编写时,它们可以不受限制地访问数据。
希望启用包含后台工作进程的模块的管理员应该格外小心。
只允许经过仔细审核的模块运行后台工作进程。
通过在shared_preload_libraries服务器配置参数中包含模块名称,可以在启动Greenplum数据库时初始化后台工作程序。
希望运行后台工作程序的模块可以通过从_PG_init()
调用RegisterBackgroundWorker(BackgroundWorker *worker)
来注册它。
通过调用函数RegisterDynamicBackgroundWorker(BackgroundWorker *worker, BackgroundWorkerHandle **handle)
,系统启动并运行后,也可以启动后台工作程序。
与只能在postmaster
中调用的RegisterBackgroundWorker
不同,必须从常规后端调用RegisterDynamicBackgroundWorker
。
因此定义了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;
char bgw_library_name[BGW_MAXLEN]; /* only if bgw_main is NULL */
char bgw_function_name[BGW_MAXLEN]; /* only if bgw_main is NULL */
Datum bgw_main_arg;
int bgw_notify_pid;
} 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
结构的副本。
bgw_main
可能为NULL; 在这种情况下,将使用bgw_library_name
和bgw_function_name
来确定入口点。
这对postmaster启动后启动的后台工作进程很有用,其中postmaster没有加载必需的库。
bgw_library_name
是库的名称,在该库中应该寻找后台工作程序的初始入口点。
除非bgw_main
为NULL,否则它将被忽略。
但是如果bgw_main
为NULL,则命名库将由工作进程动态加载,bgw_function_name
将用于标识要调用的函数。
bgw_function_name
是动态加载库中函数的名称,该库应该用作新后台工作程序的初始入口点。
除非bgw_main
为NULL,否则它将被忽略。
bgw_notify_pid
是一个Greenplum数据库后端进程的PID,postmaster应该在进程启动或退出时向其发送SIGUSR1
。
对于在postmaster启动时注册的工作进程,或者注册工作进程的后端不希望等待工作进程启动时,应该为0。
否则,它应该初始化为MyProcPid
。
一旦运行,该进程可以通过调用BackgroundWorkerInitializeConnection(char *dbname, char *username)
连接到数据库。
这允许进程使用SPI
接口运行事务和查询。
如果dbname为NULL,则会话未连接到任何特定数据库,但可以访问共享目录。
如果username为NULL,则进程将以initdb
期间创建的超级用户身份运行。
BackgroundWorkerInitializeConnection只能在每个后台进程中调用一次,无法切换数据库。
当控制到达bgw_main
函数时,信号最初被阻止,并且必须被它解除阻塞; 这是为了允许进程在必要时自定义其信号处理程序。
通过调用BackgroundWorkerUnblockSignals
可以在新进程中取消阻止信号,并通过调用BackgroundWorkerBlockSignals
来阻止信号。
如果后台工作程序的bgw_restart_time
配置为BGW_NEVER_RESTART
,
或者退出时退出代码为0或由TerminateBackgroundWorker
终止,则退出时将由postmaster自动取消注册。
否则,它将在通过bgw_restart_time
配置的时间段之后重新启动,或者如果postmaster由于后端故障而重新初始化群集时立即重新启动。
需要暂时暂停执行的后端应该使用可中断的睡眠而不是退出; 这可以通过调用WaitLatch()
来实现。
确保在调用该函数时设置WL_POSTMASTER_DEATH
标志,并在postgres
本身已终止的紧急情况下验证返回代码以提示退出。
当使用RegisterDynamicBackgroundWorker
函数注册后台工作程序时,执行注册的后端可以获得有关工作进程状态的信息。
希望这样做的后端应该将BackgroundWorkerHandle *
的地址作为RegisterDynamicBackgroundWorker
的第二个参数传递。
如果工作程序已成功注册,则此指针将使用不透明句柄进行初始化,
该句柄随后可以传递给GetBackgroundWorkerPid(BackgroundWorkerHandle *, pid_t *)
或TerminateBackgroundWorker(BackgroundWorkerHandle *)
。
GetBackgroundWorkerPid
可用于轮询工作进程的状态:返回值BGWH_NOT_YET_STARTED
表示工作进程尚未由postmaster启动;
BGWH_STOPPED
表示它已经启动但不再运行; 和BGWH_STARTED
表示它当前正在运行。
在最后一种情况下,PID也将通过第二个参数返回。
TerminateBackgroundWorker
使postmaster在运行时将SIGTERM
发送给worker,并在它不运行时立即取消注册。
在某些情况下,注册后台工作进程的进程可能希望等待工作进程启动。
这可以通过将bgw_notify_pid
初始化为MyProcPid
,
然后将在注册时获得的BackgroundWorkerHandle *
传递给WaitForBackgroundWorkerStartup(BackgroundWorkerHandle *handle,pid_t *)
函数来实现。
此函数将阻塞,直到postmaster尝试启动后台工作程序,或直到postmaster死亡。
如果后台运行器正在运行,则返回值将为BGWH_STARTED
,并且PID将被写入提供的地址。
否则,返回值将为BGWH_STOPPED
或BGWH_POSTMASTER_DIED
。
worker_spi
模块包含一个工作示例,演示了一些有用的技术。
注册后台工作进程的最大数量受max-worker-processes限制。
Parent topic: Greenplum数据库参考指南