1.6. 异步通知 #
PostgreSQL 通过
LISTEN 和
NOTIFY 命令支持异步通知。后端用
LISTEN 命令注册它对某个特定通知条件的兴趣(并可以用
UNLISTEN 命令停止监听)。当任何后端执行带该条件名的
NOTIFY
命令时,所有监听该条件的后端都会被异步通知。通知者不会向监听者传递任何附加信息。因此,通常需要通信的任何实际数据都通过一个数据库关系传递。条件名通常与相关的关系同名,但并不要求必须有相关的关系。
libpq 应用把
LISTEN 和
UNLISTEN 命令作为普通 SQL
命令提交。随后,可以通过调用
PQnotifies 检测
NOTIFY
消息的到达。
PQnotifies从后端发来的尚未处理的通知消息列表中返回下一条通知。没有待处理的通知时返回 NULL。一条通知被 PQnotifies 返回后即视为已处理,并会从通知列表中移除。PGnotify* PQnotifies(PGconn *conn); typedef struct pgNotify { char relname[NAMEDATALEN]; /* name of relation * containing data */ int be_pid; /* process id of backend */ } PGnotify;处理完
PQnotifies返回的PGnotify对象后,务必用free()释放它,以避免内存泄漏。注意
在 PostgreSQL 6.4 及之后的版本中,
be_pid是发出通知的后端的 PID,而在较早的版本中它总是你自己的后端的 PID。
第二个示例程序演示了异步通知的使用。
PQnotifies()
并不真正读取后端数据;它只是返回先前被其他
libpq
函数吸收的消息。在
libpq
的早期版本中,确保及时收到 NOTIFY
消息的唯一方法是不断地提交查询(哪怕是空查询),然后在每次
PQexec() 之后检查
PQnotifies()。这种方法虽然仍然有效,但由于浪费处理能力已被弃用。
在没有有用查询可提交时检查 NOTIFY
消息的更好办法是调用
PQconsumeInput(),然后检查
PQnotifies()。可以用 select() 等待后端数据到达,这样除非有事可做就不会消耗
CPU。(获取用于
select() 的文件描述符号的方法见
PQsocket()。)注意,无论你用
PQsendQuery/PQgetResult
提交查询还是直接用
PQexec,这样做都没有问题。但应记住在每次
PQgetResult 或
PQexec 之后检查
PQnotifies(),看查询处理期间是否有通知到来。