Postgresql 中文操作指南

34.9. Asynchronous Notification #

PostgreSQL 通过 LISTENNOTIFY 命令提供异步通知。客户端会话通过 LISTEN 命令在特定通知频道中注册对其的兴趣(并且可以使用 UNLISTEN 命令停止侦听)。当任何会话通过带有该频道名称的 NOTIFY 命令执行一个通知时,侦听特定频道的会话将异步收到通知。可以传递一个“载荷”字符串,向侦听器传达其他数据。

libpq 应用程序将 LISTENUNLISTENNOTIFY 命令作为常规 SQL 命令提交。随后可以通过调用 PQnotifies 来检测到 NOTIFY 消息的到达。

函数 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() 等待数据从服务器到达,从而在没有事情要做时不使用任何 CPU 能力。(请参见 PQsocket 以获取在 select() 中使用的文件描述符数量。)请注意,无论你用 PQsendQuery / PQgetResult 提交命令,还是仅仅使用 PQexec ,这都适用。但是,在每次 PQgetResultPQexec 后,你都应记得检查 PQnotifies ,以查看在处理命令期间是否收到了任何通知。