在 postgresql 中,为什么 _PG_init 被调用了两次?
In postgresql, Why is _PG_init called twice?
我在 postgresql 中写了一个 c 函数。这是我的初始化函数:
void _PG_init(){
int line = 0, errcode2 = 0;
char buf[1024], db_log[1024];
dbglog("first call\n");
l = (local_t*)palloc(sizeof(local_t));
if(!l) die(ERROR_NOMEM);
dbglog("first palloc local_t\n");
memset(l, 0, sizeof(local_t));
session_init_lock = 0;
sprintf(buf, "%s/" PREFIX "/privacyprot.log", getenv("HOME"));
l->logfile = fopen(buf, "a+");
if(!(l->logfile)) die(ERROR_NOMEM);
l->begin_time = time(NULL);
return;
}
我知道当这个库第一次加载时,_PG_init 将被立即调用,但是,"first call" 日志被打印了两次。如何解决这个问题,我只想要一个线程。
由于您的测试方式,您可能会看到它被调用了两次。
当它通过显式 LOAD
调用、local_preload_libraries
或调用引用该共享的 LANGUAGE c
函数加载到该进程时,每个后端进程调用一次图书馆。
是的,每个进程。 PostgreSQL 是一种 多进程架构 ,每个进程有一个 fork()
ed 连接。每个后端都可以读取 postmaster 内存,因为 fork()
使其成为写时复制,但是写入时将页面复制到进程的私有地址 space 进程无法像在多线程程序中那样通过写入全局变量进行通信.相反,他们使用显式分配的共享内存段进行通信。这是一个默认不共享的模型,与多线程编程的默认共享一切模型相反。
如果您希望 PG_init
被恰好调用一次,您必须使用 shared_preload_libraries
使您的库在启动时由 postmaster 加载,在后端得到 fork()
ed 之前。在这种情况下,它无法访问数据库或所有常用设施,因此它主要注册挂钩和回调,请求共享内存段和锁分配,然后继续正常启动。您也可以在此阶段注册后台工作进程。
通过在 postmaster 启动期间请求它自己的共享内存,您的扩展然后可以使用此内存以及 PostgreSQL 提供的其他 IPC 机制(如锁和闩锁)在后端之间进行通信。
您将在 contrib/
目录的扩展中找到共享内存的一些基本使用示例。
参见:
以及从那里链接的各种资源。
我在 postgresql 中写了一个 c 函数。这是我的初始化函数:
void _PG_init(){
int line = 0, errcode2 = 0;
char buf[1024], db_log[1024];
dbglog("first call\n");
l = (local_t*)palloc(sizeof(local_t));
if(!l) die(ERROR_NOMEM);
dbglog("first palloc local_t\n");
memset(l, 0, sizeof(local_t));
session_init_lock = 0;
sprintf(buf, "%s/" PREFIX "/privacyprot.log", getenv("HOME"));
l->logfile = fopen(buf, "a+");
if(!(l->logfile)) die(ERROR_NOMEM);
l->begin_time = time(NULL);
return;
}
我知道当这个库第一次加载时,_PG_init 将被立即调用,但是,"first call" 日志被打印了两次。如何解决这个问题,我只想要一个线程。
由于您的测试方式,您可能会看到它被调用了两次。
当它通过显式 LOAD
调用、local_preload_libraries
或调用引用该共享的 LANGUAGE c
函数加载到该进程时,每个后端进程调用一次图书馆。
是的,每个进程。 PostgreSQL 是一种 多进程架构 ,每个进程有一个 fork()
ed 连接。每个后端都可以读取 postmaster 内存,因为 fork()
使其成为写时复制,但是写入时将页面复制到进程的私有地址 space 进程无法像在多线程程序中那样通过写入全局变量进行通信.相反,他们使用显式分配的共享内存段进行通信。这是一个默认不共享的模型,与多线程编程的默认共享一切模型相反。
如果您希望 PG_init
被恰好调用一次,您必须使用 shared_preload_libraries
使您的库在启动时由 postmaster 加载,在后端得到 fork()
ed 之前。在这种情况下,它无法访问数据库或所有常用设施,因此它主要注册挂钩和回调,请求共享内存段和锁分配,然后继续正常启动。您也可以在此阶段注册后台工作进程。
通过在 postmaster 启动期间请求它自己的共享内存,您的扩展然后可以使用此内存以及 PostgreSQL 提供的其他 IPC 机制(如锁和闩锁)在后端之间进行通信。
您将在 contrib/
目录的扩展中找到共享内存的一些基本使用示例。
参见:
以及从那里链接的各种资源。