• PostGresql listen与notify命令


    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
  • 相关阅读:
    ctfhub -afr -1 2 3
    ARM 版 OpenEuler 22.03 部署 KubeSphere v3.4.0 不完全指南
    springboot+清远旅游推荐网站 毕业设计-附源码211551
    一、Linux 入门、VM 与 Linux 的安装
    用于视觉识别的深度卷积网络中的空间金字塔池化
    LeetCode --- 1417. Reformat The String 解题报告
    【C语言】预处理超级详细解析
    SAP 20策略测试简介
    Hyperledger Fabric Transaction Flow——事务处理流程
    小猿圈Java讲师分享开发9年Java进阶大全
  • 原文地址:https://www.cnblogs.com/watermeloncode/p/16543606.html