LISTEN与NOTIFY命令   

  PostgreSQL提供了client端和其他client端通过服务器端进行消息通信的机制。这种机制 是通过LISTEN和NOTIFY命令来完成的。   

1.LISTEN与NOTIFY的简单示例   

  接下来举例说明LISTEN和NOTIFY的使用方法。   

  先运行一个psql(这里称为“session1”),执行LISTEN命令,示例如下:   

osdba@osdba-laptop:~$ psql
psql (9.4betal)   
Type "help"for help.
osdba=# listen osdba;   
LISTEN   

  上面的命令“listen osdba”中的“osdba'”是一个消息通道名称,实际上也可以是其他任 何字符串。   

  再运行另一个psq1(这里称为“session2”),执行NOTIFY命令,示例如下:

osdba=# notify osdba,'hello world';   
NOTIFY   

  NOTIFY命令后的消息通道名称要与前面的LISTEN命令后的消息通道名称一致。   

  此时,sessionl还没有反应,在sessionl上随便运行一条命令,示例如下:

osdba=# select 1;
  ?c01 umn?
---------------------
  1
(1 row)
Asynchronous notification "osdba" with payload "hello world" received from server process with PID 9872.

  可以看到最后一行显示收到一个异步消息" Asynchronous notification "osdba" with payload "hello world"...."。

2. LISTEN 与 NOTIFY 的相关命令

  LISTEN 与 NOTIFY 的相关命令及两数主要有以下几个。

  口 LISTEN:监听消息通道。
  口 UNLISTEN: 取消先前的监听。
  口 NOTIFY:发送消息到消息通道中。
  口 pg_notity():与NOTIFY 命令的功能相同,也可以发送消息到消息通道中。
  口 pg_listening_ channels():调用此两数可以查询当前 session 己注册了哪些消息监听。

  下面讲解每个命令的用法。先看 LISTEN 命令,示例如下:

  LISTEN channel

  此命令比较简单,后面跟一个通道名称。如果当前会话已经被注册为该消息通道的监听器,再次执行 LISTEN 命令,此消息通道的命令不会报错,相当于什么也不做。注册消息监听后,如果不想再收到相应的消息,可以使用 UNLISTEN 命令取消监听,UNLISTEN 命令的语法格式如下:

  UNLISTEN { channel | *  }
  使用特殊的条件通配符“*”可以取消对当前会话所有监听的注册。

  下面介绍 NOTIFY 命令,示例如下:

  NoTIFY channel [ ,' payload " ]

  NOTIFY 命令发送一个通知事件,同时可以带一个可选的消息信息字符串到每个客户端应用程序,这些应用程序已经预先为当前数据库的指定名称的通道执行 LISTEN channel 命令。如果上面的命令没有指定消息信息字符串,则消息信息宇符串是空字符串。
  也可以使用西数 pg_notify() 来发送通知事件,此两数的语法格式如下:

  pg notify(text, text)

  第一个参数是消息通道的名称,第二个参数是要发送的消息信息字符串。
  调用两数 pg_listening_ channels() 查询当前 session 注册的消息监听,命令如下:

osdba=# listen osdba1;
LISTEN
osdba=# listen osdba2;
LISTEN
osdba=# select pg_listening_ channels();
pg_listening_channels
-------------------------------------------------------
  osdba1
  osdba2
(2 rows)

3. LISTEN与 NOTIFY 的使用详解

  多个session 可以同时监听同一个消息通道。当发送端发送一个消息时,所有监听者都可 能收到此消息。示例如下。

  先运行 一个psql (这里称为 sessionl”),执行LISTEN 命令,命令如下:

osdba@osdba-laptop:~$ psql
psql(9.4betal) Type "help" for help.
osdba=# listen osdba:
TISTEN

  再运行另一个psal (这里称为 “session2” ),执行 LISTEN 命令,命令如下:

osdba@osdba-laptop:~$ psql
psql (9. 4betal) Type "help" for help.
osdba=# listen osdba;
LISTEN

  运行另一个 psql(这里称为 “session3”),执行 NOTIFY 命令,命令如下:

osdba@osdba-laptop:~$ psql
psql(9.4betal) Type "help" for help.
osdba=# notify osdba, 'hello world1';
NOTIFY
osdba=# notify osdba, 'hello world2' ;
NOTIFY
osdba=#

  这时,在 session1 上随便运行一条命令,命令如下:

osdba=# select 1;
  ?column?
-----------------------------
    1
(1 row)
Asynchronous notification "osdba" with payload "hello world1" received from server process with PID 31453.
Asynchronous notification "osdba" with payload process with PID 31453. "hello world2" received from server
osdba=#

  在 session2 上随便运行一条命令,命令如下:

osdba=# select 1;
  ?column?
----------------------------------
1 (1 row)
Asynchronous notification "osdba" with payload "hello world1" received from server process with PID 31453.
Asynchronous notification "osdba" with payload "hello world2" received from server process with PID 31453.

  从上面的运行结果中可以看到 sessionl 和 session2 都可以接收到此消息。

  如果在事务中调用 NOTIFY 发送消息,实际上消息在事务提交时才会被发送,如果事务 回滚了,消息将不会被发送,示例如下 先运行一个 psql (这里称为 "session1" ),执行LISTEN 命令,命令如下:

osdba=# listen osdba;
LISTEN

  再运行另一个 psql(这里称为 "session2"),在此窗口中运行如下命令:

osdba=# begin;
BEGIN
osdba=# notify osdba, 'hello world';
NOTIFY

  上面启动了一个事务,然后调用了 NOTIFY 发送消息,但事务没有提交。然后再到 session1 中随便运行一条命令,可以看到并没有收到消息,命令如下:

osdba=# select 1;
? column?
---------------------
    1
(1 row)

  如果再到 session2 中提交事务,命令如下:

osaba=# begin;
BEGIN
osdba=# notify osdba, 'hello world';
NOTIFY
osdba=# end;
COMMIT

  这时再回到 session1 中随便运行一条命令,就可以看到收到了消息,命令如下:

osdba=# select 1;
  ?column?
----------------------------
(1 row)
Asynchronous notification "osdba" with payload "hello world" received from server process with PID 31501

  另外,使用pg_notity 函数也可以发送消息,还是前面的示例,在session2 中使用 pg_notify发送消息,命令如下。

osdba=# begin;
BEGIN
osdba=# select pg_notify('osdba', 'pg notify send') ;
  pg_notify
----------------------
(1 row)
osdba=# end;
COMMIT

  然后在 session1 中随便运行一条命令就收到了pg_notify()函数发送过来的消息,命令 如下:

osdba=# select 1;
  ?column?
-------------------------------
1 (1 row)
Asynchronous notification "osdba" with payload "pg_notify send" received from server process with PID 31501.

  如果在一个事务中发送两条消息通道名称相同、消息字符串也完全相同的消息,实际上 只有一条消息会被发送出去,示例如下。 先运行- 一个psql(这里称为 " session1 ”),执行 LISTEN 命令,命令如下:

osdba=# listen osdba;
LISTEN

  再运行另- 一个psql(这里称为 “session2”),在此窗口中运行如下命令:

osdba=# begin;
BEGIN
osdba=# notify osdba, 'hello world';
NOTIFY
osdba=# notify osdba, 'hello world';
NOTIFY osdba=# end;
COMMIT

再到 session1 中随便运行一条命令,看能收到几条消息,命令如下:

osdba=# select 1;
  ?column?
------------------------
(1 row)
Asynchronous notification "osdba" with payload "hello world" received from server process with PID 10637.

  从上面的示例中可以看到,只收到了 一条消息,由此验证了前面的结论:同一个事务中 的重复消息会自动去重。

  NOTIFY 能保证来自同一个事务的信息按照发送时的顺序交付,也能保证来自不同事务 的信息会按照事务提交的顺序交付。

  消息队列持有被发送但是未被监听会话处理的消息,这些消息太多会导致该队列变满, 此时调用 NOTIFY 命令会在提交时发生失败。不过队列通常都很大,在默认安装中是8GB, 所以一般不太会满。然而,如果一个会话执行 LISTEN 后,长时间处于一个事务中,不清理 消息就可能导致队列变满。

  注意: 在两阶段提交中不能使用 NOTIFY 命令,示例如下:

osdba=# begin;
BEGIN
osdba=# notify osdba, hello world';
NOTIFY
osdba=# PREPARE TRANSACTION 'myxid';
ERROR: NOTIFY cannot PREPARE a transaction that has executed LISTEN, UNLISTEN, or NOTIFY

PostGresql listen与notify命令的更多相关文章

  1. PostgreSQL与MySQL常用命令比较[转]

    PostgreSQL与MySQL常用命令比较 原文链接: http://www.phpwell.com/?p=174 PostgreSQL MySQL 服务启动:1)#service postgres ...

  2. postgresql的psql常用命令-4

    psql是PostgreSQL的一个命令行交互式客户端工具 1. 查看postgresql账号 [root@localhost ~]#cat /etc/passwdroot:x:0:0:root:/r ...

  3. PostgreSQL入门教程(命令行)

    初次安装完成后 1.默认生成一个名为postgres的数据库 2.一个名为postgres的数据库用户 3.这里需要注意的是,同时还生成了一个名为postgres的Linux系统用户. 下面,我们使用 ...

  4. PostgreSQL 登录时在命令行中输入密码

    有时候需要设置定时任务直接执行 sql 语句,但是 postgresql 默认需要人工输入密码,以下命令可以直接在命令行中直接填入密码 PGPASSWORD=pass1234 psql -U MyUs ...

  5. PostgreSQL客户端psql常用命令

    使用psql客户端访问数据库, 列出了psql常用命令和参数. 常用命令 -- 使用指定用户和IP端口登陆 psql -h 10.43.159.11 -p 5432 -U postgres -W -- ...

  6. PostgreSQL 初学常用实用命令

    常用命令 psql -h ip -p port -U user -d dbName 数据库 \dt(当前数据库所有表) \l(所有数据库) \c(切换数据库) \d 表名(查看表结构) table \ ...

  7. Postgresql的一些命令

    显示所有数据表: \dt 显示表结构:  \d YOUR_TABLE 进入数据库: psql DATABASE_NAME 显示所有数据库: \list 退出: \q 删除数据库: dropdb DAT ...

  8. PostgreSQL 9.5 高可用、负载均衡和复制

    高可用.负载均衡和复制 1. 不同方案的比较 共享磁盘故障转移 共享磁盘故障转移避免了只使用一份数据库拷贝带来的同步开销. 它使用一个由多个服务器共享的单一磁盘阵列.文件系统(块设备)复制 DRBD是 ...

  9. NOTIFY - 生成一个通知

    SYNOPSIS NOTIFY name DESCRIPTION 描述 NOTIFY 命令向当前数据库中所有执行过 LISTEN name, 正在监听特定通知条件的前端应用发送一个通知事件. 传递给前 ...

随机推荐

  1. 『忘了再学』Shell基础 — 13、环境变量(一)

    目录 1.用户自定义的环境变量 (1)环境变量设置 (2)查询自定义环境变量 (3)删除自定义环境变量 2.系统自带的环境变量--PATH环境变量 (1)PATH环境变量 (2)PATH环境变量的作用 ...

  2. 图解Dijkstra算法+代码实现

    简介 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的 ...

  3. Python技法:浮点数取整、格式化和NaN处理

    1. 取整的三种方法 1.1 强转int类型 这种方法会直接对浮点数的小数部分进行截断(无论是正还是负). print(int(2.7)) # 2 print(int(-2.7)) # -2 1.2 ...

  4. 【雅礼集训 2017 Day2】棋盘游戏

    loj 6033 description 给一个\(n*m\)的棋盘,'.'为可通行,'#'为障碍.Alice选择一个起始点,Bob先手从该点往四个方向走一步,Alice再走,不能走走过的点,谁不能动 ...

  5. SpringBoot Restful 接口实现

    目录 SpringBoot 核心注解 SpringBoot Restful 接口实现 封装响应数据 SpringBoot 核心注解 SpringBoot 基础入门 注解 说明 Component 声明 ...

  6. 《HALCON数字图像处理》第六章笔记

    目录 第六章 图像增强 图像增强的概念和分类 灰度变换 直方图处理 图像的平滑 图像的锐化 图像的彩色增强 我在Gitee上建了个仓库,会将学习书本的时候打的一些代码上传上去,笔记中所有代码都在仓库里 ...

  7. np.r_、np.c_、np.concatenate和np.append

    np.r_是按行连接两个矩阵,就是把两矩阵上下相加,要求列数相等,最终结果的行数为两个矩阵行数和. np.c_是按列连接两个矩阵,就是把两矩阵左右相加,要求行数相等,最终结果的列数等于两矩阵的列数和. ...

  8. vue-property-decorator

    vue-property-decorator使我们能在vue组件中写TypeScript语法,依赖于vue-class-component 装饰器:@Component.@Prop.@PropSync ...

  9. Jetpack架构组件学习(3)——Activity Results API使用

    原文地址:Jetpack架构组件学习(3)--Activity Results API使用 - Stars-One的杂货小窝 技术与时俱进,页面跳转传值一直使用的是startActivityForRe ...

  10. windows和linux系统下测试端口连通性的命令

    0. ping 1. telnet 2. ssh 3. curl 4. wget 5. tcping 6. 总结 本文地址: https://www.cnblogs.com/hchengmx/p/12 ...