pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
NOTIFY — 发出一个通知
NOTIFY name
NOTIFY 命令向当前数据库中曾为指定通知名执行过 LISTEN 的每个客户端应用发送一个通知事件。name
NOTIFY为访问同一个PostgreSQL数据库的一组进程提供了一种简单的进程间通信机制。如果需要传递结构化数据,也可以借助数据库中的表,把附加数据(而不只是通知名)从通知发送者传递给一个或多个监听者,从而构建更高层的机制。
传递给客户端的通知事件信息包括:通知名以及发出通知的会话对应的服务器进程PID。在某个数据库中使用哪些通知名以及各自含义,由数据库设计者自行决定。
常见的做法是让通知名与数据库中的某个表同名,而通知事件基本上意味着:“我改动了这张表,去看看有什么新变化”。不过,NOTIFY和LISTEN命令并不会强制这种关联。例如,数据库设计者可以使用多个不同的通知名,来标识同一张表上的不同类型变更;
当NOTIFY用于表明某张特定表发生变化时,一种很有用的编程技巧是把NOTIFY放进由表更新触发的规则中。这样一来,每当表发生变化时就会自动发出通知,应用程序员也不容易忘记这么做。
NOTIFY会以几种重要方式与 SQL 事务交互。首先,如果在事务内部执行NOTIFY,那么只有在事务提交之后,通知事件才会被递送;如果事务被中止,则其中所有命令都不会生效,NOTIFY也不例外。这种行为是合理的,但如果你期望通知立即送达,可能会感到意外。其次,如果某个正在监听的会话在事务内部收到了通知信号,那么在该事务结束(提交或中止)之前,通知事件都不会递送给它所连接的客户端。原因同样在于:如果通知在事务内部就已递送,而该事务后来又被中止,我们会希望通知也能被撤销,但服务器一旦把通知发送给客户端,就无法再把它“收回”。因此,通知事件只会在事务之间递送。由此得出的结论是,使用NOTIFY做实时信号的应用,应尽量让事务保持短小。
NOTIFY在一个重要方面的行为类似 Unix 信号:如果在短时间内多次发出同一通知名的信号,接收者可能对多次执行的NOTIFY只收到一个通知事件。因此,依赖收到通知的数量并不是一个好主意。正确的做法是用NOTIFY唤醒需要关注某事的应用,而用一个数据库对象(例如序列)来跟踪发生了什么以及发生了多少次。
执行NOTIFY的客户端自己同时也在监听同一通知条件,这是很常见的情形。在这种情况下,它会像其他监听会话一样收到一个通知事件。根据应用逻辑,这可能导致无用功,例如再次读取自己刚刚写入更新的数据库表。要避免这种额外工作,可以检查通知事件消息中提供的发出通知的服务器进程PID,是否与当前会话自身的PID(可通过libpq获得)相同。如果二者相同,就说明这是当前会话自己发出的通知回送给自己,可以直接忽略。(尽管前一段有那样的说法,但这是一种安全的技术:PostgreSQL会把自身通知与来自其他会话的通知分开保存,因此忽略自己的通知并不会让你错过来自外部的通知。)
name要发信号的通知名称(任意标识符)。
在psql中配置并执行一组 listen/notify 操作:
LISTEN virtual; NOTIFY virtual; Asynchronous notification "virtual" received from server process with PID 8448.
SQL 标准中没有NOTIFY语句。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。