DBMS_PIPE 封装(单件管道)

DBMS_PIPE 软件包允许同一实例中的两个或多个会话进行通信。

Oracle Autonomous Database on Dedicated Exadata Infrastructure 支持 Oracle Database 19c 中提供的核心 DBMS_PIPE 功能以及扩展。

See DBMS_PIPE in Oracle Database 19c PL/SQL Packages and Types Reference or Oracle Database 23ai PL/SQL Packages and Types Reference for details about the core DBMS_PIPE functionality provided in Oracle Database.

DBMS_PIPE 单例管道概述

管道功能具有多个潜在应用:外部服务接口、调试、独立事务处理和警报。

Autonomous Database 上,DBMS_PIPE 程序包扩展了支持单例管道的功能。有关更多信息,请参见 Oracle Database 19c PL/SQL Packages and Types ReferenceOracle Database 23ai PL/SQL Packages and Types Reference 中的 DBMS_PIPE

DBMS_PIPE 中的单例管道功能提供以下功能:

  • 能够在 Oracle 数据库内存中缓存和检索最多 32,767 字节的定制消息。消息大小最大为 32,767 字节适用于所有管道,包括单例管道。以前版本的 DBMS_PIPE 的最大消息大小较小。

  • 使用并发读取在多个数据库会话之间共享缓存的消息。

  • Cache Invalidation 方法:

    • 由用户控制的显式高速缓存失效。
    • 在用户指定的参数 (shelflife) 时间间隔后高速缓存失效(以秒为单位)。
  • 通过声明式且易于使用的 PL/SQL API 进行高速缓存。

  • 支持只读和读写数据库。

单例管道可以是任何受支持的 DBMS_PIPE 类型之一:

  • 隐式管道:使用 DBMS_PIPE.SEND_MESSAGE 函数使用未知的管道名称发送消息时自动创建。
  • 显式管道:使用具有用户指定的管道名称的 DBMS_PIPE.CREATE_PIPE 函数创建。
  • 公共管道:任何对 DBMS_PIPE 程序包具有 EXECUTE 权限的用户均可访问
  • 专用管道:由与管道创建者具有相同用户的会话访问。

单例管道的 DBMS_PIPE 子程序概要

此表列出了 DBMS_PIPE 子程序并简要介绍了它们。

表 - DBMS_PIPE 程序包子程序

子程序 说明

CREATE_PIPE 函数

创建管道(专用管道必需)

返回缓冲区中下一项的数据类型

在本地缓冲区中构建消息

清除命名管道的内容

RECEIVE_MESSAGE 函数

将来自命名管道的消息复制到本地缓冲区

清除本地缓冲区的内容

删除指定的管道

SEND_MESSAGE 函数

在命名管道上发送消息:如果命名管道不存在,这将隐式创建公共管道

返回唯一的会话名

访问缓冲区中的下一项

CREATE_PIPE 函数

此函数显式创建公共或专用管道。如果 private 标志为 TRUE,则将管道创建者指定为专用管道的所有者。

只能通过调用 REMOVE_PIPE 或关闭实例来删除显式创建的管道。

要创建单例管道,请将 singleton 参数设置为 TRUE。以下参数适用于单例管道:

  • singleton:指示应将管道创建为单例管道(默认值:FALSE)。

  • shelflife:(可选)在单例管道中指定缓存消息的保质期到期(以秒为单位)。它可用于单例管道中的消息隐式失效。

    发送消息时,也可以指定单例管道中的消息 shelflife(请参见 SEND_MESSAGE Function )。

语法

DBMS_PIPE.CREATE_PIPE (
   pipename     IN VARCHAR2,
   maxpipesize  IN INTEGER DEFAULT 66536,
   private      IN BOOLEAN DEFAULT TRUE,
   singleton    IN BOOLEAN DEFAULT FALSE,
   shelflife    IN INTEGER DEFAULT 0)
RETURN INTEGER;

参数

表 - CREATE_PIPE 函数参数

Parameter (参数) 说明

pipename

要创建的管道的名称。

调用 SEND_MESSAGERECEIVE_MESSAGE 时必须使用此名称。此名称在实例中必须是唯一的。

注意:不要使用以 ORA$ 开头的管道名称。这些保留供 Oracle 提供的过程使用。Pipename 不应超过 128 字节,并且不区分大小写。此时,名称不能包含全球化支持字符。

maxpipesize

管道允许的最大大小(字节)。

管道上所有消息的总大小不能超过此数量。如果消息超过此最大值,则会阻止该消息。

缺省 maxpipesize 为 66536 字节。

管道的 maxpipesize 成为管道特征的一部分,并持续存在管道的生命周期。具有较大值的 SEND_MESSAGE 调用方会导致 maxpipesize 增加。值较小的调用方使用现有较大的值。

缺省的 maxpipesize(65536) 适用于所有管道。

private

使用缺省值 TRUE 创建专用管道。

调用 SEND_MESSAGE 时,可以隐式创建公共管道。

singleton

使用 TRUE 创建单例管道。

默认值:FALSE

shelflife

在单例管道中缓存的消息的失效时间(以秒为单位)。超过指定的 shelflife 时间后,无法再从管道访问该消息。参数 shelflife 仅适用于单例管道。

缺省值为 0,这意味着消息永不失效。

返回值

表 - CREATE_PIPE 函数返回值

返回 说明

0

成功。

如果管道已存在,并且尝试创建管道的用户有权使用该管道,则 Oracle 将返回 0(表示成功),并且管道中已存在任何数据。

6

无法将现有管道转换为单例管道。

  • 具有多个现有消息的隐式管道无法转换为单例管道。
  • 对于不是单例的显式管道,DBMS_PIPE.SEND_MESSAGE 无法发送单例参数设置为 TRUE 的消息。

7

shelflife 参数指定了非零值,并且管道不是单例管道。

ORA-23322

因命名冲突而失败。

如果存在具有相同名称且由其他用户创建的管道,则 Oracle 会发出错误 ORA-23322,指示命名冲突。

异常错误

表 - CREATE_PIPE 函数异常错误

例外 说明

Null pipe name

权限错误:同名的管道已存在,不允许您使用它。

范例

创建具有 1 小时保质期的单例管道。

DECLARE
  l_status INTEGER;
BEGIN
  l_status := DBMS_PIPE.create_pipe(pipename  => 'MY_PIPE1',
                                    private   => TRUE,
                                    singleton => TRUE,
                                    shelflife => 3600);
END;
/

RECEIVE_MESSAGE 函数

此函数将消息复制到本地消息缓冲区中。

语法

DBMS_PIPE.RECEIVE_MESSAGE (
   pipename      IN VARCHAR2,
   timeout       IN INTEGER      DEFAULT maxwait,
   cache_func    IN VARCHAR2     DEFAULT NULL)
RETURN INTEGER;

参数

表 - RECEIVE_MESSAGE 函数参数

Parameter (参数) 说明

pipename

要接收消息的管道的名称。

ORA$ 开头的名称保留供 Oracle 使用。

timeout

等待消息的时间(秒)。超时为 0 可让您读取而不阻塞。

超时不包括 cache_func 参数中指定的执行高速缓存函数所用的时间。

默认值:常量 MAXWAIT,定义为 86400000(1000 天)。

cache_func

高速缓存函数名称,用于在单例管道中自动高速缓存消息。

函数的名称应该使用所有者方案完全限定:

  • OWNER.FUNCTION_NAME
  • OWNER.PACKAGE.FUNCTION_NAME

默认值:NULL

返回值

表 - RECEIVE_MESSAGE 函数返回值

返回 说明

0

成功

1

超时。如果管道是隐式创建的且为空,则将其删除。

2

管道中的记录对于缓冲区来说太大。

3

已发生中断。

8

只能在使用单例管道时指定高速缓存函数。

ORA-23322

用户没有足够的权限从管道读取。

使用说明

要从管道接收消息,请先调用 RECEIVE_MESSAGE。当您收到消息时,该消息将从管道中删除;因此,消息只能收到一次。对于隐式创建的管道,从管道中移除最后一个记录后,将删除管道。

如果您在调用 RECEIVE_MESSAGE 时指定的管道尚不存在,则 Oracle 会隐式创建管道并等待接收消息。如果消息未在指定的超时间隔内到达,则调用将返回并删除管道。

收到邮件后,必须对 UNPACK_MESSAGE 进行一次或多次呼叫才能访问邮件中的各个项目。UNPACK_MESSAGE 过程超载以解压缩 DATENUMBERVARCHAR2 类型的项目,还有两个额外的过程来解压缩 RAWROWID 项目。如果您不知道要解压缩的数据类型,请调用 NEXT_ITEM_TYPE 来确定缓冲区中下一个项目的类型。

高速缓存函数参数

单例管道支持高速缓存功能,以便在出现以下两种情况时自动在管道中缓存消息:

  • 单例管道为空。
  • 单例管道中的消息无效,因为已用 shelflife 时间。

函数的名称应该使用所有者方案完全限定:

  • OWNER.FUNCTION_NAME
  • OWNER.PACKAGE.FUNCTION_NAME

要使用高速缓存函数,调用 DBMS_PIPE.RECEIVE_MESSAGE 的当前会话用户必须具有执行高速缓存函数所需的权限。

高速缓存函数语法

CREATE OR REPLACE FUNCTION cache_function_name (
       pipename  IN VARCHAR2
) RETURN INTEGER;
Parameter (参数) 数据类型 说明

pipename

VARCHAR2

单例管道的名称。

返回 说明
0 成功
非零 DBMS_PIPE.RECEIVE_MESSAGE 返回的失败值

定义高速缓存函数,以便从单例管道的读取器会话中对复杂性进行封装和抽象。高速缓存函数中的典型操作如下:

  • 使用 DBMS_PIPE.CREATE_PIPE 为显式管道创建单例管道。
  • 在单例管道中创建要高速缓存的消息。
  • 将消息发送到单例管道,可以选择为隐式消息指定 shelflife

异常错误

表 - RECEIVE_MESSAGE 函数异常错误

例外 说明

Null pipe name

权限错误。权限不足,无法从管道中删除记录。管道由其他人拥有。

范例

DECLARE
  l_status INTEGER;
BEGIN
  l_status := DBMS_PIPE.receive_message(pipename   => 'MY_PIPE1',
                                        timeout    => 1,
                                        cache_func => 'MY_USER.MY_CACHE_FUNC');
END;
/

SEND_MESSAGE 函数

此函数在指定的管道上发送消息。

该消息包含在本地消息缓冲区中,其中填充了对 PACK_MESSAGE 的调用。可以使用 CREATE_PIPE 显式创建管道,否则将隐式创建管道。

要创建隐式单例管道,请将 singleton 参数设置为 TRUE。以下参数适用于单例管道:

  • singleton:指示应将管道创建为单例管道(默认值:FALSE)。
  • shelflife:(可选)在单例管道中指定缓存消息的保质期到期。它可用于单例管道中的消息隐式失效。

    此参数适用于隐式和显式单例管道。SEND_MESSAGE 函数中指定的 shelflife 值将覆盖在 CREATE_PIPE 函数中为显式单例管道指定的 shelflife,并且将成为在单例管道中缓存的任何新消息的缺省值。

语法

DBMS_PIPE.SEND_MESSAGE (
    pipename     IN VARCHAR2,
    timeout      IN INTEGER DEFAULT MAXWAIT,
    maxpipesize  IN INTEGER DEFAULT 65536,
    singleton    IN BOOLEAN DEFAULT FALSE,
    shelflife    IN INTEGER DEFAULT 0)
RETURN INTEGER;

参数

表 - SEND_MESSAGE 函数参数

Parameter (参数) 说明

pipename

要放置消息的管道的名称。

如果使用的是显式管道,则这是在调用 CREATE_PIPE 时指定的名称。

注意:不要使用以 'ORA$' 开头的管道名称。这些名称保留供 Oracle 提供的过程使用。Pipename 不应超过 128 字节,并且不区分大小写。此时,名称不能包含全球化支持字符。

timeout

尝试在管道上放置消息时等待的时间(以秒为单位)。

默认值为常量 MAXWAIT,定义为 86400000(1000 天)。

maxpipesize

管道允许的最大大小(字节)。

管道上所有消息的总大小不能超过此数量。如果消息超过此最大值,则会阻止该消息。默认值为 65536 字节。

管道的 maxpipesize 成为管道特征的一部分,并持续存在管道的生命周期。具有较大值的 SEND_MESSAGE 调用方会导致 maxpipesize 增加。值较小的调用方只需使用现有的较大值。

如果将 maxpipesize 指定为 SEND_MESSAGE 过程的一部分,则无需单独调用即可打开管道。如果显式创建了管道,则可以使用可选的 maxpipesize 参数覆盖创建管道大小规范。

缺省的 maxpipesize(65536) 适用于所有管道。

singleton

使用 TRUE 创建单例管道。

默认值:FALSE

shelflife

在单例管道中缓存的消息的失效时间(以秒为单位)。

超过指定的 shelflife 时间后,无法再从管道访问该消息。参数 shelflife 仅适用于单例管道。

缺省值为 0,这意味着消息永不失效。

返回值

表 - SEND_MESSAGE 函数返回值

返回 说明

0

成功。

如果管道已存在,并且尝试创建管道的用户有权使用该管道,则 Oracle 将返回 0(表示成功),并且管道中已存在任何数据。

如果以 SYSDBS/SYSOPER 身份连接的用户重新创建管道,则 Oracle 将返回状态 0,但管道的所有权保持不变。

1

超时。

此过程可能会超时,因为它无法锁定管道,或者因为管道仍然太满而无法使用。如果管道是隐式创建的且为空,则将其删除。

3

已发生中断。

如果管道是隐式创建的且为空,则将其删除。

6

无法将现有管道转换为单例管道。

  • 具有多个现有消息的隐式管道无法转换为单例管道。
  • 对于不是单例的显式管道,DBMS_PIPE.SEND_MESSAGE 无法发送单例参数设置为 TRUE 的消息。

7

shelflife 参数指定了非零值,并且管道不是单例管道。

ORA-23322

权限不足。

如果存在具有相同名称且由其他用户创建的管道,则 Oracle 会发出错误 ORA-23322,指示命名冲突。

异常错误

表 - SEND_MESSAGE 函数异常错误

例外 说明

Null pipe name

权限错误。权限不足,无法写入管道。管道是私有的,由其他人拥有。