使用 LISTEN 和 NOTIFY(或 Node JS)实时监控 Postgresql 查询更改的任何方法?

Posted

技术标签:

【中文标题】使用 LISTEN 和 NOTIFY(或 Node JS)实时监控 Postgresql 查询更改的任何方法?【英文标题】:Any way to monitor Postgresql query changes in realtime using LISTEN & NOTIFY (or NodeJS)? 【发布时间】:2018-04-04 13:30:45 【问题描述】:

所以我有一个自定义的 Postgresql 查询,它检索指定经度纬度半径内的所有行,如下所示:

SELECT *, 
earth_distance(ll_to_earth($1,$2), ll_to_earth(lat, lng)) as distance_metres
FROM RoomsWithUsers
WHERE earth_box(ll_to_earth($1,$2), $3) @> ll_to_earth(lat, lng)
ORDER by distance_metres;

在我的节点服务器中,我希望每次查询中的行数发生变化时都能收到通知。我已经研究过使用诸如pg-live-query 之类的 Node 库,但我更愿意使用与现有 Postgres LISTEN/NOTIFY 一起使用的 pg-pubsub,以避免不必要的开销。但是,据我所知,PostgreSQL TRIGGERs 仅适用于 UPDATE/INSERT/DELETE 操作,而不适用于任何特定查询本身。有什么方法可以完成我正在做的事情吗?

【问题讨论】:

对于查询返回不同的结果,您需要对相关表进行 UPDATE、INSERT 或 DELETE。所以触发器应该可以工作 WHERE 中的条件是否不可变(对于相同的参数总是给出相同的结果)? 当问题与那些数据库引擎无关时,你为什么要标记这个 sql-server 和 mysql @JuanCarlosOropeza 问题是我希望根据客户位置创建几个这样的自定义查询(即提供自定义纬度、经度、半径),我不希望每个客户都被通知为更新 RoomsWithUser 视图后,只有客户端观察该特定查询 @klin 不,可以从视图中添加/删除行,以修改给定参数集的查询结果 【参考方案1】:

您需要为在同一通道上使用LISTEN的所有客户端设置正确的触发器,以便调用NOTIFY

很难告诉您如何在触发器中准确地实现 NOTIFY 逻辑,因为它取决于以下内容:

消息的目标客户有多少? 正在评估的查询有多大/多大? 触发器能否知道查询的逻辑来评估它?

根据答案,您可能会考虑不同的方法,包括但不限于以下选项及其组合:

在无法评估结果时执行查询/视图,并缓存结果 如果可以评估查询的结果,则提供智能通知 使用payload 将更新详细信息传递给侦听器 安排查询/视图重新运行以延迟执行,如果它很重 将整个通知作为单独的工作进行

某些场景可能会变得相当复杂。例如,您可能有一个可以进行更改的主客户端,以及需要通知的多个从属客户端。在这种情况下,master 会执行查询,检查结果是否发生了变化,然后调用 PostgreSQL 服务器中的一个函数来触发所有 slave 的通知。

同样,根据手头任务的具体要求,可能会有很多变化。在您的情况下,您没有提供足够的详细信息来提供任何特定路径,但上述一般准则应该对您有所帮助。

【讨论】:

【参考方案2】:

异步和监听/通知是正确的方式!

您可以在 UPDATE/INSERT 上添加触发器并在触发器主体中执行查询,将 行数保存在简单表中,如果值更改调用通知。如果您在查询中需要多个参数组合,您可以在程序内部创建/销毁触发器。

【讨论】:

我补充说他可能应该使用存储过程进行选择,因为它允许他注册他需要使用触发器触发的查询并为“followed”表播种 在触发函数中执行可能很繁重的查询似乎是一个可怕的想法。 有我如何做到这一点的例子吗?就像如果将一行添加到我的 RoomsWithUsers 视图中一样,我只想通知满足我查询的 WHERE 子句的客户端 @Blag 所以你是说为我的选择存储一个过程,然后用我需要的参数注册一个自定义触发器? 你查到这个@BeardMagician 的底线了吗?

以上是关于使用 LISTEN 和 NOTIFY(或 Node JS)实时监控 Postgresql 查询更改的任何方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Postgres 数据库在 Java 中获得异步/事件驱动的 LISTEN/NOTIFY 支持?

在 Postgres 中使用审计表为 NOTIFY/LISTEN 创建触发器是个好主意吗?

当 PostgreSQL 中没有会话发出 LISTEN 时,NOTIFY 会发生啥?

如何在 Node.js server.listen() 中使用可选的主机名参数

node启动时, listen EADDRINUSE 报错;

为啥wait,notify和notifyAll必须在同步块或同步方法中调