Postgresql提供 监听 - 通知 的订阅服务,使得数据库客户端向服务端的指定通道注册为监听客户端,服务端在发出Notify通知时,所有已注册的监听客户端将能够收到该通知。

使用示例

服务端

-- 不带消息的通知
users=> NOTIFY test_channel;
NOTIFY-- 带消息的通知
users=> NOTIFY test_channel, 'I am payload';
NOTIFY

客户端

-- 不带消息的通知
users=> LISTEN test_channel;
LISTEN
Asynchronous notification "test_channel" received from server process with PID 9501.-- 带消息的通知
users=> LISTEN test_channel;
LISTEN
Asynchronous notification "test_channel" with payload "I am payload" received from server process with PID 9501.

注意

  • 上面的例子看起来并不像发布-订阅,因为客户端LISTEN后并不会被主动通知,而是每次要服务端NOTIFY后,客户端再去LISTEN,这其实是误会——Postgresql客户端检测通知事件的方式取决于该客户端底层应用的编程接口。支持同步轮询异步通知两种方式。很多第三方库是支持异步通知的。
  • 通道名可以使任意有效字符串,通道不需要预先创建。

命令介绍

LISTEN

LISTEN channel (channel值任意)
  • 命令干了啥

    将当前会话注册为一个channel的监听者,如果当前会话已经注册,则啥都不干

  • 何时被通知

    无论何时当命令 NOTIFY channel 被调用时,注册在该channel上的所有监听者都会被通知。

  • 合适终止监听

    当调用UNLISTEN或会话关闭时,监听终止

  • 监听原理

    客户端检测通知事件使用的方法取决于它使用的 PostgreSQL 应用程序编程接口。

    • 如果使用libpq库,只是相当于定期执行SQL命令调用PQnotifies方法查询是否有新的通知
    • 其它接口如libpgtcl提供更高级的方法来处理通知
  • 事务相关性

    LISTEN命令在事务提交时生效,如果执行LISTEN的事务最终回滚了,则LISTEN不会生效。

NOTIFY

NOTIFY channel [, payload] (payload默认要求小于8000字节, 且必须是常量)
  • 命令干了啥

    NOTIFY向每一个在channel上注册的客户端发送通知,通知可附带可选的字符串载荷payload。通知对所有用户都是可见的。

  • 通知信息包括

    • 通知的channel名
    • 发出通知的服务端的进程PID
    • 可选的payload字符串,没有时则为空字符串
  • channel命名规则

    channel没有具体的命名规则。一般来说,channel会和某个表名一致,这样对该channel发出通知在语义上表示“我修改了这个表,看看有什么新内容吧”(配套的是将这样的NOTIFY语句放入表更新的触发器中)。不过还是要具体情况具体分析

  • 事务相关性

    如果NOTIFY用于事务中,则只有当事务提交时才会真正执行通知,如果事务取消则压根不会通知。

    如果一个待接收通知的监听会话正处于事务中,则通知事件会等到它的事务处结束后在发送到它。这是合理的,因为通知发送了就不能取消,如果在事务中发送或接收,遇到想要取消通知的情况就没办法了。

    这样的缺点导致了实时性不好,因此如果要求实时性高,就要把事务写短一点。

  • 通知折叠规则

    • 一个事务中对同一个channel发送多个paylaod一样的通知,可能会被折叠成一个通知
    • 一个事务中对同一个channel发送不同的payload通知,不会执行折叠操作
    • 不同事务,无论channel和payload是否重复,都不会执行折叠操作
  • 顺序

    NOTIFY保证顺序

    • 同一事务中,通知发出的顺序按NOTIFY声明的顺序进行
    • 不同事务,通知发出的顺序按事务提交的顺序走
  • 避免额外的工作

    在一个客户端上发送NOTIFY命令,同时该客户端监听同样的channel,会出现通知发给自己的情况,此时可以通过通知中带的进程PID发现发送者就是自己,从而忽略本来要执行的逻辑,节省性能。

  • 队列

    有一个队列用于存储已经NOTIFY但还没被所有注册的客户端获取的通知,如果队列满了,则NOTIFY在提交时会失败。

    该队列默认大小为8GB,足够大多数情况。

    如果一个监听会话长时间处于事务中,则对应通知会持续累积,当队列满了一半时,会打出警告日志。

    pg_notification_queue_usage函数可以查看用了多少。

  • pg_notify(channel, payload)

    该方法执行同样的事情,好处是payload不再要求必须是常量,可以通过变量运算得到。

UNLISTEN

UNLISTEN { channel | *)}

用于将当前会话移除出channel的监听列表,*表示移除当前会话监听的所有channel。

在会话期间,使用UNLISTEN channel的方式移除监听

在会话结束时,会自动执行UNLISTEN *

参考资料

  • Postgresql-10官方手册 - LISTEN

  • Postgresql-10官方手册 - NOTIFY

  • Postgresql-10官方手册 - UNLISTEN

  • Postgresql-10官方手册 - Asynchronous Notification

Postgresql的Listen-Notify机制相关推荐

  1. java判断线程是否wait_Java并发编程之线程间通讯(上)wait/notify机制

    线程间通信 如果一个线程从头到尾执行完也不和别的线程打交道的话,那就不会有各种安全性问题了.但是协作越来越成为社会发展的大势,一个大任务拆成若干个小任务之后,各个小任务之间可能也需要相互协作最终才能执 ...

  2. Postgresql杂谈 16—Postgresql中的锁机制

    今天,我们学习下Postgresql中的锁机制.锁是数据库事务的基础,通过锁才能保证数据库在并发时能够保证数据的安全和一致,才能够达到事务的一致性和隔离性.但是任何事物都有它的两面性,引入锁同样会增加 ...

  3. ceph之Watch/Notify机制简介

    文章目录 Watch/Notify机制 1. OverView 2. Watch/Notify代码实现过程详解 2.1 librados层watch 2.2 osdc Linger Op发送 2.3 ...

  4. PostgreSQL中的MVCC机制

    MVCC,Multi-Version Concurrency Control,多版本并发控制. 一句话讲,MVCC就是用同一份数据临时保留多版本的方式,实现并发控制.它可以避免读写事务之间的互相阻塞, ...

  5. 使用PostgREST的RestAPI操作之相关软件生态系统

    使用PostgREST的RestAPI操作之相关软件生态系统 示例应用程序 tatut / postgrest-ui -PostgREST的ClojureScript UI组件 priyank-pur ...

  6. Notify通知机制解析

    Wait/Notify通知机制解析 前言 我们知道,java的wait/notify的通知机制可以用来实现线程间通信.wait表示线程的等待,调用该方法会导致线程阻塞,直至另一线程调用notify或n ...

  7. PostgreSQL体系结构之物理结构

    PostgreSQL体系结构之物理结构 数据目录中子目录和文件的用途 目录 用途 base 包含每个数据库对应的子目录的子目录 global 包含集簇范围的表的子目录,比如pg_database pg ...

  8. Postgresql安装及使用

    Postgresql安装 一.链接 二.源码安装postgresql-11.4 2.1 安装 默认端口 2.1.1 安装依赖 2.1.2 下载解压 2.1.3 编译安装 2.1.4 配置环境变量 2. ...

  9. PostgreSQL数据库集簇

    数据库集簇的逻辑结构 数据库集簇(database cluster)是指由单个PostgreSQL服务器实例管理的数据库集合.(解读:数据库集簇是集合,其元素是数据库.一个PostgreSQL服务器实 ...

  10. postgresql 集群_谁说postgresql 没有靠谱的高可用(2)

    接上期说,(没看上期的,还是先看上期,要不从这看是看不懂的) 那到底这个手动转换的过程是如何的,这个要搞一搞清楚 repmgr -f /etc/repmgr.conf standby switchov ...

最新文章

  1. java的知识点34——任务定时调度(多线程)
  2. java显式构造函数_C++中的显式构造函数
  3. 「日常训练」Skills(Codeforce Round #339 Div.2 D)
  4. inline-block空白间隙
  5. python与access选哪个_从Python连接到Access
  6. Linux下CMAKE编译jsoncpp,c – 如何为jsoncpp编写cmake模块?
  7. Segmentaion标签的三种表示:poly、mask、rle
  8. 自动完成下拉框 Select2 关键字搜索的实例(本地数据与异步获取)
  9. 如何配置虚拟机的快照报警
  10. 妙启动_十张图带你了解中国国产奶酪巨头——妙可蓝多发展情况
  11. Latex 版本简历
  12. 视频下载转换器:MovieSherlock for Mac
  13. CSS实现背景图片固定
  14. python爬虫算法是什么_Python爬虫:什么是网络爬虫
  15. 线性卷积和循环卷积(圆周卷积)
  16. 最全数据集网站汇总,绝对是一个金矿请查收!
  17. 如何实现跳转至QQ 或者QQ的加好友页面。
  18. Hadoop安装及部署
  19. 抽象类和抽象方法 abstract类和abstract方法
  20. Android 10 Camera学习笔记:Camera Framework架构

热门文章

  1. 基于python和selenium爬取JD商城商品信息并且分析用户对于产品的满意程度
  2. FreeMarker 简介
  3. 获得好资料都的渠道,老铁告别坑人的百度吧
  4. 孪生素数 所谓孪生素数指的就是间隔为 2 的相邻素数,它们之间的距离已经近得不能再近了,就象孪生兄弟一样。
  5. 毕业设计 基于单片机的小型简易录音机
  6. python爬取快手视频 多线程下载
  7. 亲爱的老狼-display的应用
  8. From blockchain consensus back to Byzantine consensus
  9. 你的眼睛应该是灰色的,像钢铁一般的颜色
  10. C#与数据库访问技术总结(三)之 Connection对象的常用方法