# 通知

NOTIFY — 生成通知

# 概要

NOTIFY channel [ , payload ]

# 描述

通知命令将通知事件与可选的“有效负载”字符串一起发送到先前已执行的每个客户端应用程序听 *渠道*对于当前数据库中的指定通道名称。所有用户都可以看到通知。

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

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

由数据库设计者定义将在给定数据库中使用的通道名称以及每个通道的含义。通常,通道名称与数据库中某个表的名称相同,并且 notify 事件本质上意味着“我更改了此表,看看它有什么新变化”。但没有这样的关联是由通知命令。例如,数据库设计人员可以使用几个不同的通道名称来表示对单个表的不同类型的更改。或者,可以使用有效负载字符串来区分各种情况。

什么时候通知用于表示对特定表的更改的发生,一种有用的编程技术是将通知在由表更新触发的语句触发器中。这样,当表格改变时,通知会自动发生,应用程序程序员不会不小心忘记这样做。

通知以一些重要的方式与 SQL 事务交互。首先,如果一个通知在事务内部执行时,除非事务被提交,否则不会传递通知事件。这是适当的,因为如果事务中止,其中的所有命令都无效,包括通知.但是,如果人们期望通知事件会立即传递,这可能会令人不安。其次,如果侦听会话在事务中接收到通知信号,则通知事件将在事务完成(提交或中止)之后才传递给其连接的客户端。同样,推理是,如果通知是在后来被中止的事务中传递的,人们会希望通知以某种方式撤消——但是一旦通知发送给客户端,服务器就不能“收回”通知。所以通知事件只在事务之间传递。这样做的结果是应用程序使用通知对于实时信号,应尽量缩短交易时间。

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

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

# 参数

渠道

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

有效载荷

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

# 笔记

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

功能pg_notification_queue_usage返回队列中当前被挂起通知占用的部分。看第 9.26 节了解更多信息。

已执行的交易通知无法为两阶段提交做好准备。

# 皮克_通知

要发送通知,您还可以使用该功能``pg_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 标准中的语句。

# 也可以看看

,不听