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

NOTIFY

NOTIFY — 生成一条通知

概要

NOTIFY channel [ , payload ]

描述

NOTIFY 命令发送一条通知事件,以及一个可选的 负载 字符串,发送给当前数据库中对指定通道名称之前已执行 LISTEN channel 的每个客户端应用程序。所有人都可以看到通知。

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

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

由数据库设计者确定在给定数据库中使用的通道名称以及每个名称含义。通常,通道名称与数据库中某个表的名称相同,且通知事件基本上表示,我更改了此表,请查看以了解新信息。但是,NOTIFYLISTEN 命令并未强制执行此类关联。例如,数据库设计者可以使用几个不同的通道名称来表示对某个表的不同类型的更改。或者,可以使用有效负载字符串来区分不同的情况。

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

NOTIFY 以某些重要方式与 SQL 事务交互。首先,如果 NOTIFY 在事务内执行,则除非提交事务,否则通知事件不会交付。这是适宜的,因为如果中止事务,则事务内所有命令均不会产生作用,包括 NOTIFY。但如果期望通知事件立即交付,则可能会令人不安。其次,如果监听会话在事务内收到通知信号,则只有在事务完成(已提交或已中止)后,才会向其连接的客户端交付通知事件。同样,原因在于如果在稍后中止的事务内交付通知,则希望通知以某种方式撤销 — 但一旦将通知发送给客户端,服务器便无法 收回 通知。所以通知事件仅在事务之间交付。结果是,使用 NOTIFY 进行实时信令的应用程序应尽量缩短其事务时间。

如果在同一事务内使用相同的有效负载字符串对同一频道名称发送多次信号,则仅会向监听器交付一次通知事件实例。另一方面,具有不同有效负载字符串的通知将始终作为不同通知交付。同样,不同事务的通知绝不会折叠到一个通知中。除了删除冗余通知的稍后实例外,NOTIFY 保证来自同一事务的通知按发送顺序交付。还保证不同事务的消息按事务提交顺序交付。

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

参数

频道

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

有效负载

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

注释

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

函数 pg_notification_queue_usage 返回当前由待处理通知占据的队列部分。有关更多信息,请参阅第 9.27 节

已执行 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 语句。

另请参阅

LISTENUNLISTENmax_notify_queue_pages