zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

PostgreSQL LISTEN 与NOTIFY命令

postgresql命令 notify listen
2023-09-14 09:13:28 时间

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

1.1 LISTEN与NOTIFY的简单示例

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

Last login: Wed Aug 31 09:49:07 2022 from 36.113.10.220
[root@MaxwellDBA ~]# sudo -i -u maxwell
[maxwell@MaxwellDBA ~]$ psql -d maxwelldb
psql (12.9)
Type "help" for help.

maxwelldb=# listen maxwelldb;
LISTEN
maxwelldb=#

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

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

Last login: Wed Aug 31 09:49:07 2022 from 36.113.10.220
[root@MaxwellDBA ~]# sudo -i -u maxwell
[maxwell@MaxwellDBA ~]$ psql -d maxwelldb
psql (12.9)
Type "help" for help.

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

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

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

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

Asynchronous notification "maxwelldb" with payload "hello world" received from server process with PID 348285.
maxwelldb=# 

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

1.2 LISTEN与NOTIFY的相关命令

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

·LISTEN:监听消息通道。

·UNLISTEN:取消先前的监听。

·NOTIFY:发送消息到消息通道中。

·pg_notify():与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注册的消息监听,命令如下:

maxwelldb=# listen maxwelldb1;
LISTEN
maxwelldb=# listen maxwelldb2;
LISTEN
maxwelldb=# select pg_listening_channels();
 pg_listening_channels 
-----------------------
 maxwelldb1
 maxwelldb2
(2 rows)

maxwelldb=#

1.3 LISTEN与NOTIFY的使用详解

多个session可以同时监听同一个消息通道。当发送端发送一个消息时,所有监听者都可能收到此消息。示例如下。先运行一个psql(这里称为“session1”),执行LISTEN命令,命令如下:

[maxwell@MaxwellDBA ~]$ psql -d maxwelldb
psql (12.9)
Type "help" for help.

maxwelldb=# listen maxwelldb;
LISTEN

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

[maxwell@MaxwellDBA ~]$ psql -d maxwelldb
psql (12.9)
Type "help" for help.

maxwelldb=# listen maxwelldb;
LISTEN
maxwelldb=#

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

[root@MaxwellDBA ~]# sudo -i -u maxwell
[maxwell@MaxwellDBA ~]$ psql -d maxwelldb
psql (12.9)
Type "help" for help.

maxwelldb=# notify maxwelldb,'hello world1';
NOTIFY
maxwelldb=# notify maxwelldb,'hello world2';
NOTIFY
maxwelldb=#

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

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

Asynchronous notification "maxwelldb" with payload "hello world1" received from server process with PID 348432.
Asynchronous notification "maxwelldb" with payload "hello world2" received from server process with PID 348432.
maxwelldb=#

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

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

Asynchronous notification "maxwelldb" with payload "hello world1" received from server process with PID 348432.
Asynchronous notification "maxwelldb" with payload "hello world2" received from server process with PID 348432.
maxwelldb=# 

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

如果在事务中调用NOTIFY发送消息,实际上消息在事务提交时才会被发送,如果事务回滚了,消息将不会被发送,示例如下。