当 PostgreSQL 中没有会话发出 LISTEN 时,NOTIFY 会发生啥?
Posted
技术标签:
【中文标题】当 PostgreSQL 中没有会话发出 LISTEN 时,NOTIFY 会发生啥?【英文标题】:What happens with a NOTIFY when no session has issued LISTEN in PostgreSQL?当 PostgreSQL 中没有会话发出 LISTEN 时,NOTIFY 会发生什么? 【发布时间】:2014-05-30 00:31:18 【问题描述】:PostgreSQL 有一个很好的监听/通知系统。 Documentation 说:
有一个队列保存已发送但未发送的通知 尚未由所有收听会话处理。如果这个队列满了, 调用 NOTIFY 的事务将在提交时失败。
但我无法找出没有侦听器的指定频道中的事件发生了什么。通知队列会溢出还是 PG 会从队列中删除这些事件?
【问题讨论】:
那么如果周围没有人,基本上一棵树就不会倒在森林里? 对不起,我听不懂你在说什么。我的问题不正确吗? 如果没有监听器,那么每条消息都已经被所有监听器处理过了。 PostgreSQL 在这种情况下不会像@IfLoop 建议的那样做任何事情。你可以试试:NOTIFY non_existing_channel;
好吧,如果我在喝咖啡休息的时候问一个空房间里的每个人是否要喝咖啡,我要等多久才能得到房间里每个人的回答?. “所有听众”与“至少一个听众”不同,
【参考方案1】:
手册中可能会更清楚,但有明确的指示表明,一旦没有会话正在积极等待通知,队列就会被清除。 Per documentation:
但是,如果会话执行
LISTEN
然后进入 交易了很长时间。队列半满后,您将看到警告 在将您指向阻止清理的会话的日志文件中。在这种情况下 您应该确保此会话结束其当前事务,以便 清理工作可以继续进行。
这意味着,如果没有人在监听(没有活动会话在同一通道上发出 LISTEN
命令),没有什么可以阻止 Postgres立即清理队列。
【讨论】:
有什么办法可以解决这个缺点吗?如果目前没有进程正在监听但将来可能会丢失任何通知,我不想丢失任何通知?我们可以保留未被收听的通知吗? @Zoran777:除了NOTIFY
,您还可以写入日志表。每个会话仅接收在它注册了LISTEN
频道之后 发出的通知。由于 pg 9.2 也没有办法获得“听众名单”。请参阅here 和here 还有其他一些优点。您可能会开始一个包含详细信息的新问题。您可以随时链接到这个以获取上下文。【参考方案2】:
当已发出NOTIFY
的事务提交时,SQL 引擎会查找LISTEN
此时的其他会话以获取此通知。
如果没有,则丢弃通知。它没有在任何地方排队。
它并没有像LISTEN documentation 那样直接解释,但正如@IfLoop cmets 所指出的,它通过严格解释来暗示:
...保存已发送但尚未发送的通知的队列 由所有监听会话处理。
零会话尚未处理意味着没有什么可以排队。
这也是有道理的,因为否则每个通知者都应该担心是否有听众,这将严重妨碍NOTIFY
的有用性。
【讨论】:
更糟。如果有一个听众,但应该有两个怎么办?发件人无法知道。发送者只能期望它知道的许多接收者。如果没有,则消息可以立即被丢弃。以上是关于当 PostgreSQL 中没有会话发出 LISTEN 时,NOTIFY 会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章
如果我们从设置中有 Facebook 会话,FBLoginView 不会发出警报