NOTIFY
NOTIFY - 生成通知
语法格式
NOTIFY channel [ , payload ]
说明
NOTIFY命令将通知事件与可选的”payload”字符串一起发送到先前已为当前数据库中的指定通道名执行LISTEN channel 的客户端应用程序。所有用户都可以看到通知。
NOTIFY 为访问同一Vastbase E100数据库的进程集合提供了一种简单的进程间通信机制。有效负载字符串可以与通知一起发送,并且可以通过使用数据库中的表将附加数据从通知程序传递给侦听器来构建用于传递结构化数据的更高级机制。
传递给客户端以获取通知事件的信息包括通知通道名称,通知会话的服务器进程PID,和有效负载字符串,如果尚未指定,则为空字符串。
数据库设计者可以定义将在给定数据库中使用的通道名称以及每个通道名称的含义。通常,通道名称与数据库中某些表的名称相同,而notify事件本质上意味着”我更改了此表,看看它是什么新的”。但NOTIFY 和 LISTEN命令并未执行此类关联。例如,数据库设计人员可以使用多个不同的通道名称来向单个表发出不同类型的更改信号。或者,有效载荷串可用于区分各种情况。
当 NOTIFY 用于表示特定表的更改发生时,一种有用的编程技术是将 NOTIFY放入由表更新触发的语句触发器中。这样,当表更改时,通知会自动发生,并且应用程序员不会意外忘记执行此操作。
NOTIFY 以某些重要方式与SQL事务交互。首先,如果在事务内执行了 NOTIFY,则除非事务已提交,否则不会传递通知事件。这是合适的,因为如果事务中止,则其中的所有命令都没有效果,包括NOTIFY。但如果人们期望立即传递通知事件,那就令人不安。其次,如果侦听会话在事务处理期间收到通知信号,则通知事件将不会在事务完成(提交或中止)之后传递到其连接的客户端。同样,原因在于,如果在稍后中止的事务中传递通知,则可能希望以某种方式撤消通知-但是一旦将通知发送到客户端,服务器就不能”收回”通知。因此,通知事件仅在事务之间传递。这样做的结果是,使用NOTIFY 进行实时信令的应用程序应该尽量缩短 事物 时间。
如果从具有相同有效负载字符串的同一事务多次发信号通知相同的通道名称,则数据库服务器可以决定仅发送单个通知。另一方面,具有不同有效负载字符串的通知将始终作为不同的通知传递。同样,来自不同事物 的通知永远不会折叠成一个通知。除了删除重复通知的后续实例外, NOTIFY保证来自同一事务的通知按发送顺序传递。还保证来自不同事务的消息按照提交的事务的顺序传递。
执行 NOTIFY的客户端通常会在同一通知通道上进行侦听。在这种情况下,它将返回通知事件,就像所有其他侦听会话一样。根据应用程序逻辑,这可能会导致无用的工作,例如,读取数据库表以查找该会话刚刚写出的相同更新。通过注意通知会话的服务器进程PID(在通知事件消息中提供)是否与自己的会话的PID(可从libpq获得)相同,可以避免这种额外的工作。当它们相同时,通知事件是一个人自己的工作反弹,可以忽略。
参数说明
channel
要发信号通知的通知信道的名称(任何标识符)。
payload
要与通知一起传递的”payload”字符串。必须将其指定为简单的字符串文字。在默认配置中,它必须短于8000个字节。 (如果需要传递二进制数据或大量信息,最好将其放在数据库表中并发送记录的密钥。)
注意事项
有一个队列可以保存已发送但尚未由所有侦听会话处理的通知。如果此队列已满,则在提交时调用NOTIFY的事务将失败。队列非常大(标准安装中为8GB),并且应该足够适合几乎所有用例。但是,如果会话执行LISTEN然后进入事务很长时间,则不会进行清理。一旦队列半满,您将在日志文件中看到警告,指向阻止清理的会话。在这种情况下,您应确保此会话结束其当前事务,以便可以继续进行清理。
函数 pg_notification_queue_usage返回当前被挂起通知占用的队列部分。已执行 NOTIFY的事务无法为两阶段提交做好准备。
pg_notify
要发送通知,您还可以使用 pg_notify(text, text)功能。该函数将通道名称作为第一个参数说明,将有效负载作为第二个参数说明。如果您需要使用非常量通道名称和有效负载,则该函数比NOTIFY 命令更容易使用。
示例
从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.