2024 年 9 月 26 日: PostgreSQL 17 发布!
支持版本:当前 (17) / 16 / 15 / 14 / 13 / 12
开发版本:devel
不支持版本:11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1

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

要与通知一起传递的 负载 字符串。这必须指定为一个简单的字符串文字。在默认配置中,它必须小于 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 语句。

提交更正

如果您在文档中发现任何不正确的内容,与您对特定功能的体验不符,或者需要进一步说明,请使用 此表格 报告文档问题。