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. python使用vosk进行中文语音识别

    操作系统:Windows10 Python版本:3.9.2 vosk是一个离线开源语音识别工具,它可以识别16种语言,包括中文. 这里记录下使用vosk进行中文识别的过程,以便后续查阅. vosk地址 ...

  2. 【leetcode】42. 接雨水

    目录 题目 题解 题目 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水. 示例 1: 输入:height = [0,1,0,2,1,0,1,3,2,1 ...

  3. Hadoop安装学习(第三天)

    学习任务: 1.解压jdk和hadoop包 2.安装jdk 3.修改hadoop配置文件 4.hadoop格式化 5.hadoop启动 出现的问题:hadoop可以正常启动,但是端口9000丢失,导致 ...

  4. ptorch常用代码梯度篇(梯度裁剪、梯度累积、冻结预训练层等)

    梯度裁剪(Gradient Clipping) 在训练比较深或者循环神经网络模型的过程中,我们有可能发生梯度爆炸的情况,这样会导致我们模型训练无法收敛. 我们可以采取一个简单的策略来避免梯度的爆炸,那 ...

  5. 关于『HTML5』第一弹

    关于『HTML5』:第一弹 建议缩放90%食用 祝各位国庆节快乐!!1 经过了「过时的 HTML」.「正当时的 Markdown」的双重洗礼后,我下定决心,好好学习HTML5  这回不过时了吧(其实和 ...

  6. 【freertos】011-信号量、互斥量及优先级继承机制源码分析

    目录 前言 11.1 任务同步 11.2 信号量概念 11.3 二值信号量 11.3.1 二值信号量概念 11.3.2 优先级翻转 11.3.3 二值信号量运作机制 11.4 计数信号量 11.4.1 ...

  7. 『忘了再学』Shell基础 — 29、AWK内置变量

    目录 1.AWK内置变量 2.练习说明 (1)$n变量练习 (2)FS变量练习 (3)NF变量和NR变量练习 3.总结: 1.AWK内置变量 AWK内置变量如下表: awk内置变量 作用 $0 代表目 ...

  8. Amazon 消息订阅对接

    亚马逊的api 谁用谁知道...... 除了坑还是坑 头疼一周整出来,分享给铁汁们 amazon 的订阅思维,我只能说外国人脑回路有点长 下面就讲讲具体流程步骤: 第一步: 参照官方教程:设置通知(A ...

  9. 在海思芯片上使用GDB远程调试

    1 前言 使用海思平台上(编译工具链:arm-himix200-linux)交叉编译 GDB 工具(使用版本8.2,之前用过10.2的版本,在编译 gdbserver 遇到编译出错的问题,因为关联了其 ...

  10. 国内外组态软件对比分析(InTouch、WinCC、iFix、iNeuOS)

    在我国自动化控制领域应用较广泛的工业自动化组态软件有Wonderware公司InTouch.西门子公司Wincc.GE公司iFix.国内也有一些传统组态软件厂商,使用的功能和形式基本上十分类似,受当时 ...