NOTIFY — 生成通知
NOTIFYchannel
[ ,payload
]
NOTIFY
命令会将一个通知事件与一个可选的“载荷”字符串一起发送给已经对指定的频道名称执行了 LISTEN
的每个客户端应用程序。通知对所有用户可见。channel
NOTIFY
为一组访问相同 PostgreSQL 数据库的进程提供了一个简单的进程间通信机制。载荷字符串可以随通知一起发送,并且可以通过使用数据库中的表来传递结构化数据的高级机制,以便从通知者传递额外数据给监听者。
传递给客户端的通知事件信息包括通知频道名称、通知会话的服务器进程PID以及载荷字符串,如果未指定,则载荷字符串为空。
数据库设计者可以定义要在给定数据库中使用的频道名称及其含义。通常,频道名称与数据库中的某个表名称相同,通知事件本质上意味着“我更改了此表,请查看它以了解最新情况”。但是 NOTIFY
和 LISTEN
命令并未强制执行任何此类关联。例如,数据库设计者可以使用几个不同的频道名称来指示对单个表的不同类型的更改。或者,载荷字符串可用于区分各种情况。
当使用 NOTIFY
来指示特定表发生的更改时,一种有用的编程技术是将 NOTIFY
放在由表更新触发的语句触发器中。这样,当表更改时,通知会自动发生,应用程序程序员也不会意外地忘记这样做。
NOTIFY
在某些重要方面与 SQL 事务进行了交互。首先,如果在事务内执行 NOTIFY
,则通知事件将不会在事务提交之前被传递。这是恰当的,因为如果事务被中止,其中所有命令都没有效果,包括 NOTIFY
。但如果有人期望通知事件立即传递,这可能会令人不安。其次,如果一个监听会话在事务内接收到通知信号,则在事务完成(提交或中止)之后,通知事件才会被传递给其连接的客户端。同样,原因是如果在稍后被中止的事务内传递了通知,人们会希望以某种方式撤销通知——但服务器一旦将通知发送给客户端就无法“收回”。因此,通知事件仅在事务之间传递。其结果是,使用 NOTIFY
进行实时信令的应用程序应尽量保持事务简短。
如果在同一事务中多次使用相同的频道名称和相同的载荷字符串进行信号发送,则只向监听者传递一个通知事件实例。另一方面,具有不同载荷字符串的通知将始终作为不同的通知传递。同样,来自不同事务的通知将永远不会被折叠成一个通知。除了丢弃重复通知的后续实例外,NOTIFY
保证来自同一事务的通知将按照发送顺序传递。也保证来自不同事务的消息将按照事务提交的顺序传递。
执行 NOTIFY
的客户端通常也会监听相同的通知频道。在这种情况下,它将收到一个通知事件,就像所有其他监听会话一样。根据应用程序逻辑,这可能会导致无用的工作,例如,读取数据库表以查找该会话刚刚写入的更新。通过注意通知事件消息中提供的通知会话的服务器进程PID是否与自己的会话PID(可从 libpq 获取)相同,可以避免这种额外的工作。当它们相同时,通知事件就是自己的工作反弹回来的,可以忽略。
channel
要信号发送的通知频道的名称(任何标识符)。
payload
要随通知一起通信的“载荷”字符串。这必须指定为一个简单的字符串字面量。在默认配置下,它必须短于 8000 字节。(如果需要传输二进制数据或大量信息,最好将其放入数据库表中,并发送记录的键。)
有一个队列,用于保存已发送但尚未被所有监听会话处理的通知。如果此队列已满,调用 NOTIFY
的事务将在提交时失败。队列非常大(在标准安装中为 8GB),并且对于几乎所有用例都应该足够大。但是,如果某个会话执行 LISTEN
然后进入长时间事务,则不会进行清理。一旦队列填满一半,您将在日志文件中看到警告,指向阻止清理的会话。在这种情况下,您应该确保该会话结束其当前事务,以便清理可以继续进行。
函数 pg_notification_queue_usage
返回当前被挂起通知占用的队列的比例。有关更多信息,请参阅 第 9.27 节。
已执行 NOTIFY
的事务无法为两阶段提交做好准备。
从 psql 配置并执行监听/通知序列
LISTEN virtual; NOTIFY virtual; Asynchronous notification "virtual" received from server process with PID 8448. NOTIFY virtual, 'This is the payload'; Asynchronous notification "virtual" with payload "This is the payload" received from server process with PID 8448. LISTEN foo; SELECT pg_notify('fo' || 'o', 'pay' || 'load'); Asynchronous notification "foo" with payload "payload" received from server process with PID 14728.
SQL 标准中没有 NOTIFY
语句。
如果您在文档中看到任何不正确的内容、与您对特定功能的体验不符或需要进一步澄清的内容,请使用 此表单 报告文档问题。