> PostgreSQL9.6 中文手册 > 后台工作者进程

shared_preload_libraries之外的任何机制载入共享库时,这种情况会在所有的平台上发生。即便是使用shared_preload_libraries机制,在 Windows 上使用了EXEC_BACKEND的情况下,地址空间布局变化也仍然会发生。因此,这个 API 的大部分使用者应该把这个域设置为 NULL。如果这个域为非 NULL,它会优先于bgw_library_namebgw_function_name

bgw_library_name是应该在其中定位后台工作者初始入口点的库名称。所指的库将被工作者进程动态载入并且bgw_function_name将被用来标识要调用的函数。如果从核心代码载入一个函数,应该设置bgw_main

bgw_function_name是一个动态载入库中的一个函数名,该函数将被用作一个新后台工作者的初始入口点。

bgw_main_arg是后台工作者主函数的Datum参数。不管是通过bgw_main还是通过bgw_library_namebgw_function_name的组合指定这个函数,这个主函数应该有一个单一的Datum类型的参数,并且返回voidbgw_main_arg将被作为参数传递。此外,全局变量MyBgworkerEntry指向注册时传入的BackgroundWorker结构的一份拷贝,工作者会发现检查这个结构会很有用。

在 Windows (以及任何定义了EXEC_BACKEND的地方)上或者动态后台工作者中,用引用的方式传递Datum是不安全的,只有传值才安全。如果要求一个参数,最安全的方式是传递一个 int32 或者其他的小型值,并且把它当做共享内存中分配的一个数组的索引来使用。如果被传递的是一个cstring或者text这样的值,那么在新的后台工作者进程中该指针将不会有效。

bgw_extra可以包含要传递给后台工作者的额外数据。与bgw_main_arg不同,这个数据不会被作为一个参数传递给工作者的主函数,而是按照上面所述通过MyBgworkerEntry来访问。

bgw_notify_pid是一个PostgreSQL后端进程的PID, 当后台工作者进程启动或者退出时,postmaster会向这个PID所指的进程发送SIGUSR1。 对于在postmaster启动时注册的工作者,它应该为0;或者注册该工作者的后端不希望等待该工作者启动时,它也应该为0。否则,它应该被初始化为MyProcPid

一旦运行起来,进程可以通过调用BackgroundWorkerInitializeConnection(char *dbname, char *username)或者BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid)来连接到一个数据库。这使得该进程可以使用SPI接口运行事务和查询。 如果dbname为NULL或者dboidInvalidOid,该会话没有连接到任何特定数据库,但共享的目录可以被访问。 如果username为NULL或者useroidInvalidOid,该进程将以在initdb阶段创建的超级用户身份运行。 在每一个后台进程中,只能调用两者之一,并且只能调用一次,所以不可能切换数据库。

当控制到达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 给工作者(如果它在运行),并且在它不再运行时尽快解除注册。

在某些情况下,一个注册后台工作者的进程可能希望等待该工作者启动起来。其实现方式是:把 bgw_notify_pid初始化成MyProcPid并且接着 把注册时得到的BackgroundWorkerHandle *传递给 WaitForbackgroundWorkerStartup(BackgroundWorkerHandle *handle, pid_t *)函数。 这个函数将阻塞直到postmaster已经尝试启动该后台工作者,或者直到postmaster死亡。如果后台 工作者正在运行,返回值将是BGWH_STARTED,并且其PID将被写入到所提供的地址。 否则,返回值将是BGWH_STOPPED或者 BGWH_POSTMASTER_DIED

如果一个后台工作者通过服务器编程接口(max_worker_processes限制。

上一篇:
下一篇: