支持的版本:当前17) / 16 / 15 / 14 / 13
开发版本:devel
不支持的版本:12 / 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 语句。

提交更正

如果您在文档中发现任何不正确、与您使用特定功能的经验不符或需要进一步澄清的内容,请使用此表单报告文档问题。