postgresql - Postgres 通知不会自动到达

标签 postgresql notifications observers

我在一个终端 A 打开 psql(Arch Linux 上的 PostgreSQL 9.5.4)并发出 LISTEN "notif";

然后在另一个终端 B 中运行以下脚本 (psql -f myscript.sql)。

这将创建一个包含两个触发器的表。如果在 send 为 TRUE 的位置添加了一行,则一个触发器会触发;如果行已更新,使得 send 从 FALSE 变为 TRUE,则另一个触发器会触发。两个触发器都会发送通知。

DROP TRIGGER IF EXISTS do_notif ON notif;
DROP TRIGGER IF EXISTS do_notif2 ON notif;
DROP TABLE IF EXISTS notif;

CREATE TABLE notif (id INT PRIMARY KEY, send BOOLEAN, msg TEXT);

CREATE OR REPLACE FUNCTION post() RETURNS TRIGGER AS $$
BEGIN
    PERFORM pg_notify('notif', '+' || NEW.id::TEXT || ',' || coalesce(NEW.msg, '(null)'));
    RETURN NEW;
END $$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION post2() RETURNS TRIGGER AS $$
BEGIN
    PERFORM pg_notify('notif', '~' || NEW.id::TEXT || ',' || coalesce(NEW.msg, '(null)'));
    RETURN NEW;
END $$ LANGUAGE plpgsql;

CREATE TRIGGER do_notif AFTER INSERT ON notif
    FOR EACH ROW WHEN (NEW.send)
    EXECUTE PROCEDURE post();
CREATE TRIGGER do_notif2 AFTER UPDATE OF send ON notif
    FOR EACH ROW WHEN (NEW.send AND NOT OLD.send)
    EXECUTE PROCEDURE post2();

-- LISTEN "notif";

INSERT INTO notif VALUES (1, FALSE, 'update');
INSERT INTO notif VALUES (2, TRUE, 'insert');
UPDATE notif SET send = TRUE;
UPDATE notif SET send = FALSE;
UPDATE notif SET send = TRUE;

START TRANSACTION;
INSERT INTO notif VALUES (10, FALSE, 'a'), (11, TRUE, 'b'), (12, TRUE, 'c');
UPDATE notif SET send = TRUE WHERE id = 10;
COMMIT

我希望相关的 INSERT 和 UPDATE 查询会导致触发器被调用,它会发送通知,并在终端 A 中接收。

这不会发生。我必须在终端 A 中再次手动运行 LISTEN "notif";,这会立即给我丢失的通知。

如果我取消注释该脚本中的 LISTEN "notif";,则运行该脚本 (B) 的 psql 实例将在相关位置向终端写入通知(在将 send 设置为 TRUE 的非事务性插入/更新之后,以及事务之后)。

但是 A 仍然不显示这些,除非我在 A 中再次运行 LISTEN "notif"; (或任何其他查询,例如 选择真;)。这不是终端缓冲问题,因为仅在 A 中按 ENTER 不会导致出现通知。

PostgreSQL 似乎不会立即跨不同的连接或不同的进程传递通知,但会在监听器与生成通知的进程相同时立即传递。

最佳答案

psql 在每个命令后检查通知队列(更具体地说,在从服务器收到任何结果后)。所以你可以使用一次listen channel,随后的每个命令都会检查是否有新的通知。

基于libpq.c 标准库的程序以相同的方式运行,使用the function PQnotifies 检查通知队列。从服务器接收数据后。他们还有另一种可能。如果在特定时间没有与服务器通信,他们可以使用函数 PQconsumeInput 刷新通知队列。通过这种方式,他们以异步方式接收通知。驱动程序的通知支持当然可以在更高级别实现。

关于postgresql - Postgres 通知不会自动到达,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39927011/

相关文章:

mysql - Laravel Eloquent 没有将属性保存到数据库(可能是 mysql)

javascript - Polymer 1.X - 复杂的观察者不开火

postgresql - 如何使用 go pg CRUD Postgres Point 数据类型

postgresql - 保证 upsert 为 `RETURNING`,同时限制存储的数据

mysql - 如何首先获取订单最多的供应商列表

Android - 如何创建永久通知

laravel - 如何在流明中使用preferredLocale?

linux - 我的 Linux 程序如何在不修改任何系统配置文件的情况下获得计算机即将进入休眠状态的通知?

android - 尽管数据没有改变,但一些 fragment 观察者在从返回堆栈弹出后触发

swift - Vapor,使用 PostgreSQL 流畅地保存/创建复杂模型