34.8. 异步通知

PostgreSQL 通过LISTENNOTIFY命令提供异步通知。Client 端会话使用LISTEN命令在特定的通知通道中注册其兴趣(并且可以使用UNLISTEN命令停止监听)。当任何会话执行带有该通道名称的NOTIFY命令时,将异步通知在特定通道上侦听的所有会话。可以传递“有效负载”字符串,以将其他数据传递给侦听器。

libpq 应用程序将LISTENUNLISTENNOTIFY命令作为普通 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指针就足够了; relnameextra字段不代表单独的分配。 (这些字段的名称是历史名称;特别是,通道名称与关系名称没有任何关系.)

Example 34.2提供了一个示例程序,说明了异步通知的用法。

PQnotifies实际上没有从服务器读取数据;它只是返回先前被另一个 libpq 函数吸收的消息。在古老的 libpq 版本中,确保及时接收NOTIFY消息的唯一方法是不断提交命令,甚至是空命令,然后在每个PQexec之后检查PQnotifies。尽管这仍然有效,但不建议这样做,因为这浪费了处理能力。

当您没有有用的命令要执行时,检查NOTIFY条消息的更好方法是调用PQconsumeInput,然后检查PQnotifies。您可以使用select()await 数据从服务器到达,因此除非有其他事情要做,否则不使用 CPU 电源。 (请参阅PQsocket以获取要与select()一起使用的文件 Descriptors 号.)请注意,无论您是使用PQsendQuery/PQgetResult提交命令还是简单地使用PQexec都可以。但是,您应该记住在每个PQgetResultPQexec之后检查PQnotifies,以查看在处理命令期间是否有任何通知进入。