PostgreSQL
通过 LISTEN 和
NOTIFY
命令提供异步通知。
一个客户端会话用
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 32.2 给出了一个演示异步通知使用的示例程序。
PQnotifies
实际上并不从服务器读取数据;
它只是返回先前被另一个
libpq
函数吸收的消息。
在
libpq
的古老发行版中,
确保及时收到
NOTIFY
消息的唯一方式是不断提交命令,
甚至是空命令,
然后在每次
PQexec
之后检查
PQnotifies。
虽然这样做仍然可行,
但它作为对处理能力的浪费已被弃用。
当你没有什么有用的命令可执行时,
一种更好的检查
NOTIFY
消息的方式是调用
PQconsumeInput
,
然后检查
PQnotifies。
你可以使用
select()
来等待来自服务器的数据到达,
从而在没有事情可做时不消耗任何
CPU 能力。
(参见
PQsocket
来获得与
select()
一起使用的文件描述符编号。)
注意,
无论你是用
PQsendQuery/PQgetResult
提交命令,
还是简单地使用
PQexec,
这样做都能正常工作。
不过,
你应当记得在每次
PQgetResult 或
PQexec
之后检查
PQnotifies,
看看在命令处理期间是否有任何通知进来。