NOTIFY

通知-生成通知

Synopsis

NOTIFY channel [ , payload ]

Description

NOTIFY命令将通知事件以及可选的“有效载荷”字符串发送到每个 Client 端应用程序,该 Client 端应用程序先前为当前数据库中的指定通道名称执行了LISTEN channel。通知对所有用户可见。

NOTIFY为访问同一 PostgreSQL 数据库的一组进程提供了一种简单的进程间通信机制。可以将有效负载字符串与通知一起发送,并且可以通过使用数据库中的表将其他数据从通知程序传递到侦听器来构建用于传递结构化数据的高级机制。

传递给 Client 端的通知事件的信息包括通知通道名称,通知会话的服务器进程 PID 和有效负载字符串,如果未指定,则为空字符串。

由数据库设计人员决定要在给定数据库中使用的通道名称以及每个通道的含义。通常,通道名称与数据库中某些表的名称相同,并且 notify 事件本质上意味着“我更改了该表,看看它以了解新功能”。但是NOTIFYLISTEN命令没有强制这种关联。例如,数据库设计人员可以使用几个不同的通道名称向单个表发出不同种类的更改 signal。替代地,有效载荷串可以用于区分各种情况。

当使用NOTIFY来表示特定表发生更改时,一种有用的编程技术是将NOTIFY放入由表更新触发的语句触发器中。这样,当表被更改时,通知会自动发生,并且应用程序程序员不会意外忘记这样做。

NOTIFY以某些重要方式与 SQL 事务进行交互。首先,如果在事务内部执行了NOTIFY,则直到(除非)提交事务后才传递通知事件。这是适当的,因为如果事务中止,则其中的所有命令都无效,包括NOTIFY。但是,如果有人期望立即发送通知事件,可能会感到不安。其次,如果侦听会话在事务内时接收到通知 signal,则通知事件要等到事务完成(提交或中止)之后才传递到其连接的 Client 端。同样,这样做的理由是,如果通知是在事务中传递的,而该事务后来被中止,则人们希望以某种方式撤消该通知-但是,一旦将通知发送给 Client 端,服务器将无法“取回”该通知。因此,通知事件仅在事务之间传递。结果是,使用NOTIFY进行实时信令的应用程序应尝试使其事务简短。

如果使用相同的有效负载字符串从同一事务中多次发出相同的通道名称 signal,则数据库服务器可以决定仅传递单个通知。另一方面,具有不同有效负载字符串的通知将始终作为不同的通知传递。同样,来自不同事务的通知将永远不会折叠成一个通知。 NOTIFY除了在以后删除重复通知的实例之外,保证来自同一事务的通知按其发送 Sequences 进行传递。还可以保证来自不同事务的消息以提交事务的 Sequences 传递。

执行NOTIFY的 Client 端通常在同一通知通道上进行监听。在这种情况下,它将像其他所有监听会话一样返回通知事件。根据应用程序逻辑,这可能会导致无用的工作,例如,读取数据库表以查找该会话刚刚写出的相同更新。通过通知通知会话的服务器进程 PID(在通知事件消息中提供)是否与自己会话的 PID(可从 libpq 获取)相同,可以避免此类额外的工作。当它们相同时,通知事件就是一个人自己的工作反弹,可以忽略。

Parameters

  • channel

    • 要发出 signal 的通知通道的名称(任何标识符)。
  • payload

    • 与通知一起传达的“有效载荷”字符串。必须将其指定为简单的字符串 Literals。在默认配置中,它必须小于 8000 个字节。 (如果需要传递二进制数据或大量信息,则最好将其放入数据库表中并发送记录的键.)

Notes

有一个队列,其中包含已发送但尚未被所有侦听会话处理的通知。如果此队列已满,则调用NOTIFY的事务将在提交时失败。队列很大(标准安装中为 8GB),并且对于几乎所有用例,其大小都应足够。但是,如果会话执行LISTEN然后进入事务很长时间,则无法进行清理。一旦队列半满,您将在日志文件中看到警告,指出您指向阻止清除的会话。在这种情况下,您应确保该会话结束其当前事务,以便可以进行清理。

函数pg_notification_queue_usage返回未决通知当前占用的队列部分。有关更多信息,请参见Section 9.25

已执行NOTIFY的事务无法准备进行两阶段提交。

pg_notify

要发送通知,您还可以使用功能pg_notify(text, text)。该函数将通道名称作为第一个参数,将有效负载作为第二个参数。如果需要使用非恒定通道名称和有效负载,则此功能比NOTIFY命令更易于使用。

Examples

从 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.

Compatibility

SQL 标准中没有NOTIFY语句。

See Also

LISTEN, UNLISTEN