On this page
33.8. 异步通知
PostgreSQL 通过LISTEN
和NOTIFY
命令提供异步通知。Client 端会话使用LISTEN
命令在特定的通知通道中注册其兴趣(并且可以使用UNLISTEN
命令停止监听)。当任何会话执行带有该通道名称的NOTIFY
命令时,将异步通知在特定通道上侦听的所有会话。可以传递“有效负载”字符串,以将其他数据传递给侦听器。
libpq 应用程序将LISTEN
,UNLISTEN
和NOTIFY
命令作为普通 SQL 命令提交。 NOTIFY
消息的到达随后可以通过调用PQnotifies
来检测。
函数PQnotifies
从服务器收到的未处理通知消息列表中返回下一个通知。如果没有挂起的通知,它将返回一个空指针。从PQnotifies
返回通知后,该通知将被视为已处理,并将从通知列表中删除。
PGnotify *PQnotifies(PGconn *conn);
typedef struct pgNotify
{
char *relname; /* notification channel name */
int be_pid; /* process ID of notifying server process */
char *extra; /* notification payload string */
} PGnotify;
处理PQnotifies
返回的PGnotify
对象后,请确保使用PQfreemem
释放它。释放PGnotify
指针就足够了; relname
和extra
字段不代表单独的分配。 (这些字段的名称是历史名称;特别是,通道名称与关系名称没有任何关系.)
Example 33.2提供了一个示例程序,说明了异步通知的用法。
PQnotifies
实际上没有从服务器读取数据;它只是返回先前被另一个 libpq 函数吸收的消息。在古老的 libpq 版本中,确保及时接收NOTIFY
消息的唯一方法是不断提交命令,甚至是空命令,然后在每个PQexec
之后检查PQnotifies
。尽管这仍然有效,但不建议这样做,因为这浪费了处理能力。
当您没有有用的命令要执行时,检查NOTIFY
条消息的更好方法是调用PQconsumeInput
,然后检查PQnotifies
。您可以使用select()
await 数据从服务器到达,因此除非有其他事情要做,否则不使用 CPU 电源。 (请参阅PQsocket
以获取要与select()
一起使用的文件 Descriptors 号.)请注意,无论您是使用PQsendQuery
/PQgetResult
提交命令还是简单地使用PQexec
都可以。但是,您应该记住在每个PQgetResult
或PQexec
之后检查PQnotifies
,以查看在处理命令期间是否有任何通知进入。