Postgresql 中文操作指南
Description
NOTIFY 命令会将一条通知事件和一个可选的“有效负载”字符串发送到已在当前数据库中对指定的通道名称执行过 LISTEN _channel_ 的每个客户端应用程序。所有人都可以看到通知。
NOTIFY 为访问同一 PostgreSQL 数据库的进程集合提供了一种简单的进程间通信机制。可以 همراه با通知发送一个有效负载字符串,并且可以通过使用数据库中的表来从通知者传递给监听者(们)其他数据,以此构建传递结构化数据的更高级机制。
向客户端传递的通知事件信息包括通知通道名称、发送通知的会话服务器进程 PID 和有效负载字符串,如果未指定有效负载字符串,则为空字符串。
数据库设计人员负责定义在给定数据库中将使用的通道名称及其各自的含义。通常来说,通道名称与数据库中某个表的名称相同,而通知事件本质上表示“我更改了此表,查看一下以了解有什么新变化”。但 NOTIFY 和 LISTEN 命令并不会强制执行此类关联。例如,数据库设计人员可以用几个不同的通道名称来表示对同一张表所做的不同类型的更改。此外,也可以使用有效负载字符串来区分各种情况。
当 NOTIFY 用于表示对特定表所做更改的发生时,一种有用的编程技术是在由表更新触发的语句触发器中放置 NOTIFY 。通过这种方式,当表发生更改时可以自动发出通知,并且应用程序程序员不会忘记意外地执行此操作。
NOTIFY 以一些重要方式与 SQL 事务交互。首先,如果 NOTIFY 在事务中执行,则不会在提交事务之前传递通知事件。这是合适的,因为如果事务中止,则事务中的所有命令均已失效,包括 NOTIFY 。但如果原本期望立即传递通知事件,可能会令人不安。其次,如果在某个事务中接收到一条通知信号,则在完成事务(已提交或中止)之后,才会将通知事件传递到它所连接的客户端。同样,理由是如果在某个稍后被中止的事务中传递了通知,则会希望以某种方式撤销该通知 — 但服务器一旦向客户端发送通知,就无法“收回”。因此,只能在事务之间传递通知事件。这样做的结果是, NOTIFY 应用程序用于实时信令时,应该尝试保持事务的精简。
如果在同一事务中多次使用相同有效负载字符串发出同一个通道名称信号,则只会在监听器之间传递一个通知事件实例。另一方面,具有不同有效负载字符串的通知将始终作为不同的通知进行传递。同样,来自不同事务的通知将永远不会折叠到一个通知中。除了删除重复通知的后面实例外, NOTIFY 还保证以发送的顺序传递来自同一事务的通知。同样保证的是,按照提交事务的顺序传递来自不同事务的消息。
执行 NOTIFY 的客户端经常会监听它本身的同一个通知通道。在这种情况下,它将获得一条通知事件,就像所有其他监听会话一样。根据应用程序逻辑,这可能会导致无用的工作,例如读取数据库表以查找该会话刚刚写入的相同更新。如果发现发送通知的会话的服务器进程 PID(在通知事件消息中提供)与自己的会话 PID(libpq 提供)相同时,可以避免这些额外工作。当它们相同的时候,通知事件是自己工作的反弹,可以忽略。
Parameters
-
channel
-
要发出信号的通知通道的名称(任何标识符)。
-
-
payload
-
要 همراه با通知进行通信的“有效负载”字符串。该字符串必须指定为一个简单的字符串文字。在默认配置中,该字符串必须短于 8000 字节。(如果需要通信二进制数据或海量信息,最好将其放入一个数据库表中,然后发送该记录的键。)
-
Notes
有一个队列保存已发送但尚未由所有监听会话处理的通知。如果此队列已满,则调用 NOTIFY 的事务将在提交时失败。这个队列很大(标准安装中为 8GB),应该足够满足几乎所有用例。但是,如果某个会话执行了 LISTEN ,然后又进入了很长时间的事务,则不会进行任何清理。当队列已满的时候,你将在日志文件中看到警告,指示你查看正在阻止清理的会话。在这种情况下,你应该确保会话结束当前事务,以便清理可以继续。
pg_notification_queue_usage 函数返回当前由未决通知占用的队列部分。有关更多信息,请参见 Section 9.26 。
已执行 NOTIFY 的事务不能对两阶段提交做好准备。
Examples
从 psql 配置并执行一个 listen/notify 序列:
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.