Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16

NOTIFY

NOTIFY — 生成通知

概要

NOTIFY channel [ , payload ]

描述

NOTIFY 命令会将通知事件以及一个可选的 有效负载 字符串发送到当前数据库中为指定频道名称先前执行了 LISTEN channel 的每个客户端应用程序。所有用户都可以看到通知。

NOTIFY 为访问同一 PostgreSQL 数据库的进程集合提供了一个简单的进程间通信机制。有效负载字符串可以与通知一起发送,并且可以通过使用数据库中的表来从通知者传递给监听者(们) 附加数据,从而构建用于传递结构化数据的高级机制。

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

数据库设计人员负责定义将在给定数据库中使用的通道名称以及每个名称的含义。通常,通道名称与数据库中某个表的名称相同,而通知事件本质上表示 我更改了此表,查看一下有什么新内容。但 NOTIFYLISTEN 命令并不强制执行此类关联。例如,数据库设计人员可以使用几个不同的通道名称来表示对单个表的不同类型的更改。或者,可以使用有效负载字符串来区分各种情况。

NOTIFY 用于表示对特定表的更改发生时,一种有用的编程技术是将 NOTIFY 放在由表更新触发的语句触发器中。通过这种方式,当表更改时,通知会自动发生,并且应用程序员不会意外忘记执行此操作。

NOTIFY 以一些重要方式与 SQL 事务进行交互。首先,如果在事务内部执行 NOTIFY,则只有在提交事务后才会传递通知事件。这是合适的,因为如果事务中止,则其中所有命令都将无效,包括 NOTIFY。但如果期望立即传递通知事件,这可能会令人不安。其次,如果侦听会话在事务中收到通知信号,则只有在事务完成后(提交或中止)才会将通知事件传递给连接的客户端。同样,原因是如果在稍后中止的事务中传递通知,则希望通知以某种方式撤消 - 但服务器无法在将通知发送给客户端后 收回 通知。因此,通知事件仅在事务之间传递。这带来的结果是,使用 NOTIFY 进行实时信令的应用程序应尽量保持事务简短。

如果在同一事务中使用相同的通道名称多次发出具有相同有效负载字符串的信号,则只向侦听器传递通知事件的一个实例。另一方面,具有不同有效负载字符串的通知将始终作为不同的通知传递。类似地,来自不同事务的通知永远不会折叠到一个通知中。除了删除重复通知的后面实例,NOTIFY 保证来自同一事务的通知按发送顺序传递。还保证不同事务中的消息按事务提交的顺序传递。

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

参数

channel

要发信号的通知通道的名称(任何标识符)。

payload

要与通知一起传达的 payload 字符串。这必须指定为一个简单的字符串文字。在默认配置中,它必须短于 8000 字节。(如果需要传达二进制数据或大量信息,最好将其放入数据库表中并发送记录的键。)

注释

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

函数 pg_notification_queue_usage 返回当前由挂起的通知占用的队列部分。有关更多信息,请参见 第 9.26 节

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

pg_notify

要发送通知,您还可以使用函数 pg_notify(text, text)。该函数将通道名称作为第一个参数,将有效负载作为第二个参数。如果您需要使用非常量通道名称和有效负载,则该函数比 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 语句。

另请参阅

LISTENUNLISTEN