PostgreSQL通过LISTEN和NOTIFY命令提供异步通知。客户端会话可使用LISTEN命令注册其感兴趣的特定通知通道(也可以用UNLISTEN命令停止监听)。当任何会话执行带有该通道名的NOTIFY命令时,所有监听该通道的会话都会异步收到通知。还可以传递一个“载荷”字符串,向监听者传递附加数据。
libpq应用把LISTEN、UNLISTEN和NOTIFY命令作为普通 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指针本身就足够了;relname和extra域并不表示独立分配的内存(这些域名是历史遗留的,尤其是通道名称与关系名称并无关联)。
Example 32.2给出了一个示例程序展示异步通知的使用。
PQnotifies实际上并不从服务器读取数据;它只是返回之前已被其他libpq函数吸收的消息。 在较早版本的libpq中,及时收到NOTIFY消息的唯一方法是不断提交命令,哪怕是空命令,然后在每次PQexec后检查PQnotifies。 虽然这种方法仍然有效,但由于效率过低,现已废弃。
当你没有可用的命令提交时,一种更好的检查NOTIFY消息的方法是调用PQconsumeInput ,然后检查PQnotifies。 你可以使用select()等待服务器数据到达,这样在无事可做时就不会浪费CPU资源(参见PQsocket以获得可传给select()的文件描述符)。 注意不管是用PQsendQuery/PQgetResult提交命令还是简单地使用PQexec,这种方法都能正常工作。 不过,你应该记住在每次PQgetResult 或 PQexec之后检查PQnotifies,看看在命令的处理过程中是否有通知到达。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。