调用云函数和外部过程

在内部部署 Oracle Database(Enterprise、Standard、Express、Personal Editions)中,可以在 PL/SQL、Java 或 C 中编写用户定义的函数,以提供 SQL 或 SQL 内置函数中不可用的功能。可以在 SQL 语句中随时随地调用这些用户定义的函数。请参阅关于用户定义的函数

从 Oracle Database 19c 开始,您可以使用 SQL 中的嵌入式 Python 执行功能创建、存储和执行 Python 脚本。请参见 Embedded Python Execution using OML4Py

Oracle Autonomous AI Database on Dedicated Exadata Infrastructure 支持您编写 SQL 函数来调用云中的无服务器计算服务,例如 OCI,从而将用户定义的功能扩展到云端 Functions 和 AWS Lambda Functions 或 External Procedures(外部过程),包括 C/C++ 例程、Shell 或 Python 脚本—在 Autonomous AI Database 外部的 OCI 计算 VM 中执行。

关于云函数和外部过程

用户定义的函数可用于从数据库中的 PL/SQL 或 SQL 代码调用外部可用的函数。您可以使用用户定义的函数调用以下外部函数:

  • Oracle Cloud Infrastructure Functions :Oracle Cloud Infrastructure Functions 是完全托管、多租户、高度可扩展、按需提供的函数即服务平台。Oracle Cloud Infrastructure Functions 基于企业级 Oracle Cloud Infrastructure 构建,由 Fn Project 开源引擎提供支持。有关更多信息,请参见 OCI 函数概述
  • AWS Lambda 函数:AWS Lambda 是一种无服务器事件驱动的计算服务,它允许您为几乎任何应用程序或后端服务运行代码,而无需预配或管理服务器。有关更多信息,请参见 AWS Lambda
  • 外部过程:外部过程是用第三代语言(例如 C)编写的函数,或者可以作为 SQL 函数或 PL/SQL 过程或函数调用的 OS shell 脚本或 Python 脚本。有关详细信息,请参阅什么是外部过程

调用 OCI 云函数作为 SQL 函数

显示在 Autonomous AI Database on Dedicated Exadata Infrastructure 中调用 OCI 云函数作为 SQL 函数的步骤。

在继续执行这些步骤之前,假定您已在 OCI 租户和区间中创建并部署了 OCI 函数。有关详细信息,请参见 OCI Functions

当您使用 OCI 函数后,您将使用 DBMS_CLOUD 和 DBMS_CLOUD_FUNCTION PL/SQL API 在 Autonomous AI Database 中创建 SQL 包装函数目录,这些函数通过其 API 端点引用和调用各自的云功能。您将使用 DBMS_CLOUD_FUNCTION API 管理数据库应用程序中的函数。

  1. 使用 DBMS_CLOUD.CREATE_CREDENTIAL 过程创建身份证明。

    提供 OCI 租户用户的 API 私钥(创建 API 密钥时下载的点 - 点 - 点文件的内容)作为身份证明对象、密钥的指纹、租户 OCID 和用户 OCID。请参阅所需的密钥和 OCID

    SET DEFINE OFF
    BEGIN
      DBMS_CLOUD.CREATE_CREDENTIAL (
           credential_name => 'OCI_CRED', -- provide a string as the name
           user_ocid       => 'user_ocid', -- provide the OCID string for the user, obtained from OCI Console User Profile
           tenancy_ocid    => 'tenancy_ocid', -- provide the OCID string for the tenancy, obtained from OCI Console User Profile
           private_key     => 'private_key', -- provide the content of the dot-pem file that you downloaded when you created the API Key
           fingerprint     => 'fingerprint' -- provide the fingerprint string for the API key
      );
    END;
    /

    这将创建 OCI_CRED 身份证明对象。

    有关更多信息,请参见CREATE_CREDENTIAL Procedure

  2. 使用 DBMS_CLOUD_FUNCTION.CREATE_CATALOG 过程创建目录对象。

    目录是一组包装函数,它们通过其 API 端点引用和调用各自的云功能。提供身份证明对象、云服务提供商名称(在本例中为 OCI)和 OCI 区域 ID(在本例中为 PHX)以及 OCI 函数所在的 OCI 区间 ID。

    BEGIN
    DBMS_CLOUD_FUNCTION.CREATE_CATALOG (
        credential_name  => 'OCI_CRED',
        catalog_name     => 'OCI_DEMO_CATALOG',
        service_provider => 'OCI',
        cloud_params     => '{"region_id":"phx", "compartment_id":"compartment_id"}'
    );
    END;
    /

    这将创建 OCI_DEMO_CATALOG 目录对象。

    有关更多信息,请参见CREATE_CATALOG Procedure 。可以查询 DBA_CLOUD_FUNCTION_CATALOG 视图USER_CLOUD_FUNCTION_CATALOG 视图来检索数据库中所有云功能目录的列表。

  3. 可以使用 DBMS_CLOUD_FUNCTION.LIST_FUNCTIONS 过程列出目录中的所有云功能。

    SET PAGESIZE 1000
    
    VAR function_list CLOB;
    
    BEGIN
        DBMS_CLOUD_FUNCTION.LIST_FUNCTIONS (
          credential_name  => 'OCI_CRED', 
          catalog_name     => 'OCI_DEMO_CATALOG',
          function_list    => :function_list
     );
    END;
    /
    
    PL/SQL procedure successfully completed.
    
    SELECT JSON_QUERY (:function_list, '$' RETURNING VARCHAR2(32676) pretty) AS search_results FROM dual;
    
    SEARCH_RESULTS
    ------------------------------------------------------------------------------------------------
    [
      {
        "functionName"   : "create_par",
        "functionId"     : "ocid.funfc.oc1.phx.aaaa_example", 
        "invokeEndpoint" : "https://dw.us.func.oci.oraclecloud_example.com"
      },
      {
        "functionName"   : "fintech",
        "functionId"     : "ocid.funfc.oc1.phx.bbbb_example"
        "invokeEndpoint" : "https://dw.us.func.oci.oraclecloud.com_example"
      },
      {
        "functionName"   : "jwt_codec",
        "functionId"     : "ocid.funfc.oc1.phx.jwt_code_example", 
        "invokeEndpoint" : "https://dw.us.func.oci.oraclecloud_example.com"
      },
      {
        "functionName"   : "oci-objectstorage-create-par-python",
        "functionId"     : "ocid.funfc.oc1.phx.aaaaaaaas_example", 
        "invokeEndpoint" : "https://dw.us.func.oci.oraclecloud_example.com"
      },
      {
        "functionName"   : "run_dbt",
        "functionId"     : "ocid.funfc.oc1.phx.aaaaaaaav_example",
        "invokeEndpoint" : "https://dw.us.func.oci.oraclecloud_example.com"
      }
    ]

    有关更多信息,请参见LIST_FUNCTIONS Procedure

  4. 创建 SQL 包装函数。可以使用以下两种方法之一从目录创建包装 SQL 函数,这些函数调用各自的云函数:

    • 您可以使用 DBMS_CLOUD_FUNCTION。SYNC_FUNCTIONS 从目录对象生成 SQL 包装的过程。
    • 可以使用 DBMS_CLOUD_FUNCTION 手动创建各个包装函数。CREATE_FUNCTION 过程。
    1. SYNC_FUNCTIONS :SYNC_FUNCTIONS 会自动将目录中的包装函数与在创建目录的区域、区间和租户中定义的云函数的完整列表同步(创建和/或更新)。
      BEGIN
       DBMS_CLOUD_FUNCTION.SYNC_FUNCTIONS (
              catalog_name => 'OCI_DEMO_CATALOG'
       );
      END;
      /

      这将创建一个 PL/SQL 包装器,用于将新函数添加到目录中并删除已从目录中删除的函数的包装器。

      您可以使用以下查询为给定当前用户验证同步结果。

      SHOW user
      TEST_USER
      
      SELECT object_name FROM sys.all_objects WHERE owner='TEST_USER' AND object_type='FUNCTION';
      
      OBJECT_NAME
      --------------------------------------------------------------------------------
      CREATE_PAR
      FINTECH
      JWT_CODEC
      OCI-OBJECTSTORAGE-CREATE-PAR-PYTHON
      RUN_DBT

      有关更多信息,请参见SYNC_FUNCTIONS Procedure

    2. CREATE_FUNCTION :可以在目录中手动创建 SQL 函数,该函数使用 DBMS_CLOUD.CREATE_FUNCTION 调用其各自的云函数。

      VAR function_args CLOB;
      
      EXEC :function_args := TO_CLOB('{"command": "VARCHAR2", "value": "VARCHAR2"}');
      
      BEGIN
          DBMS_CLOUD_FUNCTION.CREATE_FUNCTION (
              credential_name  => 'OCI_CRED',
              catalog_name     => 'OCI_DEMO_CATALOG',
              function_name    => 'FINTECH_FUNCTION',
              function_id      => 'ocid1.fnfunc.oc1.phx.aaabbbcccc_example',
              input_args       => :function_args
       );
      END;
      /

      这将在 OCI_DEMO_CATALOG 目录中创建 FINTECH_FUN 函数,作为对 FUNCTION_ID 参数引用其端点的相应云函数的引用。调用目录中的函数及其参数将在 OCI 中运行相应的云函数,并提供云函数返回的输出。

      注意:

      OCI 函数的名称可能与 FINTECH_FUNCTION 完全不同。创建此引用时,只会考虑您作为 function_id 参数输入提供的 OCI 函数的 OCID。
    3. CREATE_FUNCTION with custom return types and response handlers :手动创建函数允许您创建定制返回类型和响应处理程序,如以下示例所示。

      首先创建一个返回类型和函数的响应处理程序。

      CREATE OR REPLACE TYPE fintech_rt AS OBJECT (
          status VARCHAR2(1000),  
          output CLOB
      );
      /
      Type created.
      
      CREATE OR REPLACE FUNCTION fintech_response_handler(function_response IN CLOB) 
      RETURN fintech_rt
      IS
            l_comp     fintech_rt;
            l_json_obj JSON_OBJECT_T;
            status     VARCHAR2(1000);
            output     CLOB;
      BEGIN
            l_json_obj := JSON_OBJECT_T.parse(function_response); 
            status     := l_json_obj.get('STATUS').to_string;
            output     := l_json_obj.get('RESPONSE_BODY').to_string;
            l_comp     := fintech_rt(status,output);
            RETURN l_comp;
      END;
      /
      Function created.

      接下来,在手动创建 SQL 包装函数期间使用此类型和响应处理程序。

      VAR input_param CLOB;
      VAR l_return_type VARCHAR2(100);
      VAR l_response_handler VARCHAR2(1000);
      
      -- Define function parameters
      exec :input_param       := TO_CLOB('{"command": "VARCHAR2", "value": "VARCHAR2"}');
      
      PL/SQL procedure successfully completed.
      
      exec :l_return_type     := 'fintech_rt';
      
      PL/SQL procedure successfully completed.
      
      exec :l_response_handler := 'fintech_response_handler';
      
      PL/SQL procedure successfully completed.
      
      BEGIN
          DBMS_CLOUD_FUNCTION.CREATE_FUNCTION (
              credential_name  => 'OCI_CRED',
              catalog_name     => 'OCI_DEMO_CATALOG',
              function_name    => 'FINTECH_FUNCTION',
              function_id      => 'ocid1.fnfunc.oc1.phx.aaabbbcccc_example',
              input_args       => :input_param,
              return_type      => :l_return_type,
              response_handler => :l_response_handler
       );
      END;
      /

      可以查询 DBA_CLOUD_FUNCTION 视图USER_CLOUD_FUNCTION 视图视图来检索数据库中所有函数的列表。

      有关更多信息,请参见CREATE_FUNCTION Procedure

      创建函数后,可以对函数执行 DESCRIBE 来获取其返回详细信息。

      DESC fintech_fun
      COLUMN STATUS format a30
      COLUMN OUTPUT format a30

      然后可以调用该函数,为输入参数提供值。

      SET SERVEROUTPUT ON
      
      DECLARE
          l_comp fintech_rt;
      BEGIN
          l_comp := fintech_fun(command=>'tokenize',value => 'PHI_INFORMATION');
      
          DBMS_OUTPUT.put_line ('Status of the function   =  '|| l_comp.status);
          DBMS_OUTPUT.put_line ('Response of the function =  '|| l_comp.output);
      END;
      /

      这将通过调用 OCI_DEMO_CATALOG 目录中的函数引用 oocid1.funfn.oci.phx.aaaaaa_example 来调用 fintech_fun 云函数。

  5. 可以使用 DROP_FUNCTION 过程删除现有函数。

    BEGIN
        DBMS_CLOUD_FUNCTION.DROP_FUNCTION (
            catalog_name  => 'OCI_DEMO_CATALOG',
            function_name => 'fintech_fun');
    END;
    /

    这将从 OCI_DEMO_CATALOG 目录中删除 FINTECH_FUN 函数。

    有关更多信息,请参见DROP_FUNCTION Procedure

  6. 可以使用 DROP_CATALOG 过程删除现有目录。

    BEGIN
        DBMS_CLOUD_FUNCTION.DROP_CATALOG (
            catalog_name => 'OCI_DEMO_CATALOG'
      );
    END;
    /

    这将从数据库中删除 OCI_DEMO_CATALOG

    有关更多信息,请参见DROP_CATALOG Procedure

调用 AWS Lambda 函数作为 SQL 函数

显示在 Autonomous AI Database on Dedicated Exadata Infrastructure 中调用 AWS 远程函数作为 SQL 函数的步骤。

在继续执行这些步骤之前,假定您已在 AWS 租户中创建并部署了 AWS Lambda 函数。有关详细信息,请参见 AWS Lambda

要访问 AWS lambda 函数,需要在 Oracle Cloud Infrastructure 中配置必要的策略。有关更多信息,请参见 Creating an IAM policy to access AWS Lambda resourcesUsing resource-based policy for Lambda

当您使用 AWS Lambda 函数后,您将使用 DBMS_CLOUD 和 DBMS_CLOUD_FUNCTION PL/SQL API 在 Autonomous AI Database 中创建 SQL 包装函数目录,该目录通过其 API 端点引用和调用各自的云功能。您将使用 DBMS_CLOUD_FUNCTION API 管理数据库应用程序中的函数。

  1. 使用过程 DBMS_CLOUD.CREATE_CREDENTIAL 使用 AWS 密钥作为身份证明对象来创建身份证明。
    SET DEFINE OFF
    
    BEGIN
      DBMS_CLOUD.CREATE_CREDENTIAL (
        credential_name => 'AWS_CRED',
        username        => 'access_key_ID', -- ID of Secret Key
        password        => 'secret_access_key' -- Secret Key password
      );
    END;
    /

    这将创建 AWS_CRED 身份证明对象。

    有关更多信息,请参见CREATE_CREDENTIAL Procedure

  2. 使用 DBMS_CLOUD_FUNCTION.CREATE_CATALOG 过程创建目录对象。

    目录是一组包装函数,它们通过其 API 端点引用和调用各自的云功能。提供身份证明对象、云服务提供商名称(在本例中为 AWS)和 AWS Lambda 函数所在的 AWS 区域 ID(在本例中为 ap-northeast-1)。

    BEGIN
        DBMS_CLOUD_FUNCTION.CREATE_CATALOG (
            credential_name  => 'AWS_CRED', 
            catalog_name     => 'AWS_DEMO_CATALOG', 
            service_provider => 'AWS',
            cloud_params     => '{"region_id":"ap-northeast-1"}'
     );
    END;
    /

    这将创建 AWS_DEMO_CATALOG 目录对象。

    有关更多信息,请参见CREATE_CATALOG Procedure 。可以查询 DBA_CLOUD_FUNCTION_CATALOG 视图USER_CLOUD_FUNCTION_CATALOG 视图来检索数据库中所有目录的列表。

    其余步骤/操作(即 LIST_FUNCTIONS 过程、SYNC_FUNCTIONS 过程、CREATE_FUNCTION 过程、DROP_FUNCTION 过程和 DROP_CATALOG 过程)的使用与 OCI 云功能中所述的相同。请参阅将 OCI 云函数作为 SQL 函数调用

外部过程概览

概述了外部过程及其在专用基础结构应用程序上的自治 AI 数据库中的使用。

外部过程是用第三代语言编写的函数,作为 SQL 函数或 PL/SQL 过程或函数调用。SQL 和 PL/SQL 最适合在数据库中快速高效地处理数据和事务处理。外部过程可以通过在专用外部 VM 中执行计算和内存密集型任务,并将结果返回到数据库来补充 SQL 和 PL/SQL。这些任务的典型例子是科学和工程问题,其计算库存在于 Linux 操作系统中(并且不容易移植到数据平台),脱机数据分析,实时设备和过程的控制等。

您可以在 Autonomous AI Database 中调用外部过程并使用用户定义的函数。您无需在数据库中执行这些过程,而是将可执行代码放置在专用的定制 OCI Linux VM 中,该 VM 预配了用于执行 C 程序、Shell 脚本和 Python 脚本的容器和运行时,以及 Oracle SQL*Net 库,以便从数据库远程执行 SQL。

注意:

外部过程的远程主机必须是从 OCI 市场预配并在合适的 OCI 虚拟云网络 (VCN) 中配置的 OCI Linux EXTPROC VM。有关详细信息,请参见 System Configuration in OCI for External Procedures and Scripts

Remote execution on OCI Linux EXTPROC VM is supported only by Autonomous AI Database on Dedicated Exadata Infrastructure on Oracle Public Cloud starting with version 19.30, and in Oracle Database 26ai, starting with version 23.26.1. Exadata Cloud@Customer 上的 Autonomous AI Database on Dedicated Exadata Infrastructure 数据库尚不支持此功能 (ExaCC)。

外部过程和脚本的系统配置

显示预配 EXTPROC VM 的步骤,以及配置 OCI 网络和计算以执行外部过程的步骤。

该体系结构至少包含以下资源:

  • 在 OCI 租户的 OCI 区间中预配的 OCI 虚拟云网络。
  • 自治 AI 数据库,作为自治容器数据库 (ACD) 下的实例创建,该数据库从基于 Oracle Public Cloud 上的 Exadata 基础结构创建的自治 Exadata VM 集群 (AVMC) 预配。
  • 作为 OCI Marketplace EXTPROC 堆栈的一部分预配的 EXTPROC VM。

作为最佳实践,AVM 集群将放置在 VCN 中的专用子网中。将根据 OCI 租户中的自治 AI 数据库要求配置默认路由表和 VCN 的安全列表。VCN 可能有一个默认路由表和一个默认安全列表,您可以在其中定义所有路由和安全规则。(可选)如果 Autonomous AI Database 应用和专用子网中的其他资源需要出站访问互联网,则可以为 VCN 配置 NAT 网关。

将 ExtProc VM 引入此拓扑时,请执行以下最小的 OCI 网络配置步骤。

  • 您必须能够登录到 ExtProc VM 以使用 C/C++ 中实施的外部过程构建共享库 (dot-so),检查和配置 VM 和容器,并执行其他此类操作。
  • 典型做法是将 EXTPROC VM 配置为位于 VCN 中的公共子网中。在这种情况下,您必须在 VCN 中创建互联网网关(如果管理员尚未配置)。

    注意:

    EXTPROC VM 不能位于 CIDR 范围为 10.x.x.x 的子网中。如果 EXPROC VM 的 IP 地址为 10.x.x.x,它将无法与 Autonomous AI Database 进行通信。

  • 必须在 VCN 的安全列表中定义入站规则,才能通过 SSH 登录通过端口 22 访问 VM。您还必须在 VCN 的安全列表中定义出站规则,以允许 ADBD 通常访问目标端口 16000,或者访问所有目标端口。请参见 OCI Networking Access and Security
  • 在预配 EXTPROC VM 堆栈的过程中,您将提供 AVMC 的所有客户端 IP 地址。您将从 AVM 集群的 OCI 仪表盘中获取这些 IPv4 客户端 IP 地址。
  • 随后,预配工具将自动创建名为 nsg_acl 的网络安全组 (NSG)。此 NSG 将具有入站规则,允许 Autonomous Database Dedicated Client IP 地址作为唯一可以访问端口 16000 目标的源。

高级主题

  • 如果托管 ExtProc VM 和 Autonomous AI Database 的子网位于同一 VCN 中,则无需在 VCN 的路由表中指定任何特殊的路由规则。如果托管 ExtProc VM 和 ADBD 的子网位于不同的 VCN 中,则必须实施 VCN 对等连接。请参阅 VCN 对等连接
  • 如果您选择将 ExtProc VM 配置为位于专用子网中,则必须能够通过堡垒/跳转服务器登录到 VM 并仅启用入站到 ExtProc VM,并安全地访问专用子网中的其他资源,例如 Autonomous AI Database 。有关详细信息,请参见 OCI Networking Guides

使用外部过程实施用户定义的函数

  1. 从 OCI MarketPlace 预配和配置 EXTPROC VM

    1. 登录 OCI 控制台,网址为 http://cloud.oracle.com 。有关详细信息,请参阅登录 Oracle Cloud Infrastructure 控制台
    2. 从 Oracle Cloud Infrastructure 左侧导航菜单中,下拉到市场,然后在“市场”下单击所有应用程序
    3. 在搜索栏中输入“EXTPROC”,然后单击“搜索”。您将看到两个小部件 - 一个标记为堆栈,另一个标记为图像。
    4. 选择名为 Stack 的窗口部件(这很重要)。这将转到 Oracle Autonomous Database EXTPROC Agent 详细信息页,其中提供了有关堆栈的堆栈版本、发布日期和发行说明。在此页上,单击启动堆栈按钮。这将转到下一个“启动堆栈”页。
    5. 在 "Launch Stack"(启动堆栈)页面上:

      • 版本下拉列表中,选择堆栈的软件包版本。
      • 区间下拉列表中,选择要预配 EXTPROC VM 的区间的名称。除非您有特定的理由不这样做,否则请选择与 ADBD 相同的区间(作为最佳做法,避免为任何资源使用根区间)。查看 System Configuration for External Procedures and Scripts ,为区间做出相应选择。
      • 接受条款和条件并单击 Launch Stack(启动堆栈)

      这将转到下一页 - 创建堆栈向导。

    6. 在此页中,提供 namedescriptionCompartment name 、Terraform 版本和任何标记信息。区间名称是必需的,也是向此页中的向导输入的最重要内容。然后单击下一步
    7. 这会将您带到 EXTPROC VM(也称为 EXTPROC 代理)的配置变量页。此页面的第一部分收集有关 EXTPROC 库和 wallet 密码的信息。
      • 对于外部库,提供要允许从专用基础结构上的自治 AI 数据库中调用的库列表,这些库以逗号 (,) 分隔。这些共享库将包含以 C/C++ 编写的外部过程,这些过程最好是在 VM 本身中编译和构建(以匹配体系结构和环境)。

        注意:

        鉴于您仍在创建 EXTPROC VM 的过程中,请记下您在此处提供的共享库的名称。当 VM 可用并且您使用 C/C++ 开发外部过程时,您必须记得使用上面提供的确切名称编译和构建库/库。
      • 对于 Wallet Password ,为将在 ExtProc VM 中创建的 wallet 文件提供密码。将生成 wallet 和自签名证书,以便在专用基础结构上的自治 AI 数据库与 EXTPROC 代理 VM 之间进行双向 TLS 验证。
    8. 配置变量页的第二部分涉及 EXTPROC VM 的网络配置。
      • 对于区间,从下拉菜单中选择 VCN 的区间名称。在上面的示例中,它显示为 adbd。理想情况下,自治 AI 数据库和 EXTPROC VM 将托管在同一 VCN 中,即使在不同的(专用和公共)子网中也是如此。
      • 对于网络策略,选择使用现有 VCN 和子网。如上一节中所述,在 ExtProc 开发工作的此阶段,您可能需要使用 VCN、AVMC 和 Autonomous AI Database 实施系统架构。

        注意:

        另一种选择是为 EXTPROC VM 代理创建新的 VCN 和子网及其自己的配置策略。如 System Configuration for External Procedures and Scripts 中所述,如果您选择将 EXTPROC VM 放置在不同于 Autonomous AI Database 的 VCN 中,则必须对等 VCN。
      • 跳过 EXTPROC Agent Access Type 的下一个条目。此字段不适用于 Autonomous AI Database on Dedicated Exadata Infrastructure
    9. 接下来,在标记为 "Private Endpoint IP Addresses"(专用端点 IP 地址)的字段中,输入配置了数据库的 AVMC 的所有客户端 IP 地址。您可以从 OCI 控制台仪表盘获取 AVMC 的这些客户端 IP 地址。
    10. 接下来,提供 VCN 和子网的详细信息。

      注意:

      EXTPROC VM 不能位于 CIDR 范围为 10.x.x.x 的子网中。如果 EXPROC VM 的 IP 地址为 10.x.x.x,它将无法与 Autonomous AI Database 进行通信。
    11. 配置页面的最后一部分涉及 EXTPROC VM 代理的计算配置。
      • 对于区间,从下拉菜单中选择区间名称。建议您在与专用基础结构上的自治 AI 数据库、VCN 和子网相同的区间中托管 VM,以最大程度地减少故障排除。
      • 对于配置OCPU 数内存大小 (GB) ,根据外部过程的工作量特征输入值。
      • 对于添加 SSH 密钥,在 Linux OS、MacOS 或 Windows 系统中生成 SSH 公共密钥和私有密钥文件。打开一个终端窗口,然后运行以下命令之一(ED25519 是现代、更安全的算法;旧系统支持 RSA 加密算法):
        ssh-keygen -t ed25519 -C "your_email@example.com" (OR)
        ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

        这将生成私钥文件 ssh-key-<date-time-id>.key 和公钥文件 ssh-key-<date-time-id>。key.pub。将 SSH 公共密钥的内容复制粘贴到窗口中,或者将 .pub 文件拖放到窗口中。

      • 单击下一步
    12. 这将转到“Review(复查)”页面。查看所有输入,然后选中运行应用复选框,然后单击创建

      这将启动 OCI 资源管理器以创建 EXTPROC VM 堆栈。成功完成 ORM 作业后,将创建并运行 EXTPROC VM。

  2. 收集 DBMS_CLOUD_FUNCTION API 输入的 EXTPROC VM 系统信息

    您必须提供 EXTPROC VM 系统信息作为 Autonomous AI Database 中 DBMS_CLOUD_FUNCTION API 的输入,以便从数据库调用外部过程。

    1. 从 Oracle Cloud Infrastructure 左侧导航菜单的下拉菜单到“计算”,选择为 EXTPROC VM 预配指定的区间,然后查看列出区间中所有 VM 的仪表盘。ORM 作业将使用规范名称 EXTPROC-agentEXTPROC-agent-<setofnumbers> 创建 EXTPROC VM。这将是 EXTPROC VM 实例的主机名。单击此条目将转到显示系统详细信息的页面 - IPV4 公共和专用地址(IPv4 和 IPv6)、子网和映像详细信息。
    2. 使用您在 ExtProc 堆栈创建期间提供的 SSH 密钥和 IP 地址登录到 ExtProc VM。VM 上的默认用户是 opc. sudo,成为用户 oracle。
      ➜  ~ ssh -i ssh-key-<date-time-id>.key opc@<Public-IP-Address>
      Wed Nov 19 10:46:25 GMT 2025: EXTPROC Agent intialization completed.
      
      Activate the web console with: systemctl enable --now cockpit.socket
      
      Last login: Thu Nov 20 20:10:54 2025 from <client-IP-address>
      
      [opc@extproc-agent-170798 ~]$ whoami
      opc
      
      [opc@extproc-agent-170798 ~]$ sudo su - oracle
      Last login: Wed Nov 19 19:07:24 GMT 2025 on pts/0

      EXTPROC VM 将有一个正在运行的带有 Oracle SQL*Net 监听程序的 Podman 容器。在容器内,将提供包含必要配置文件(如 sqlnet.ora、listener.ora)的 Oracle 客户端环境以及用于与 Autonomous AI Database 进行安全通信的 wallet 文件。

    3. 从 VM 中配置的 Podman 容器收集 PL/SQL API 所需的系统信息(在 OS 级别,然后收集系统信息)。该容器运行 Oracle Listener 来接收来自 Autonomous AI Database 上 SQL 和 PL/SQL 应用程序的远程执行请求,并且是外部过程的运行时执行引擎。
      • 在 Linux OS 中,EXTPROC VM 主机的 FQDN(全限定域名)。
      • 从 Podman 容器中,从监听程序状态开始,即数据库连接到 VM 的 EXTPROC VM 上的端口。
      • 从 Podman 容器中,从 sqlnet.ora 规范中获取 wallet 文件的位置。
      • 通过使用 orapki 工具检查 wallet 文件,Wallet 证书的标识名 (Distinguished Name,DN) 参数值。
      [oracle@extproc-agent-170798 ~]$ hostname -f
      extproc-agent-170798.subnet-name.vcn-name.oraclevcn.com
      
      [oracle@extproc-agent-170798 ~]$ podman ps
      CONTAINER ID  IMAGE                              COMMAND     CREATED       STATUS                 PORTS       NAMES
      86d81c4df6ff  ghcr.io/oracle/adb-extproc:latest              23 hours ago  Up 23 hours (healthy)              adb-extproc
      
      [oracle@extproc-agent-170798 ~]$ podman exec -it 86d81c4df6ff bash
      
      (base) [oracle@extproc-agent-170798 admin]$ lsnrctl status
      
      LSNRCTL for Linux: Version 23.26.0.0.0 - for Oracle Cloud and Engineered Systems on 20-NOV-2025 09:25:54
      
      Copyright (c) 1991, 2025, Oracle.  All rights reserved.
      
      Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1)))
      STATUS of the LISTENER
      ------------------------
      Alias                     LISTENER
      Version                   TNSLSNR for Linux: Version 23.26.0.0.0 - for Oracle Cloud and Engineered Systems
      Start Date                19-NOV-2025 17:19:58
      Uptime                    0 days 16 hr. 5 min. 55 sec
      Trace Level               off
      Security                  ON: Local OS Authentication
      SNMP                      OFF
      Listener Parameter File   /u01/app/oracle/product/23.0.0.0/client_1/network/admin/listener.ora
      Listener Log File         /u01/app/oracle/diag/tnslsnr/extproc-agent-170798/listener/alert/log.xml
      Listening Endpoints Summary...
        (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1)))
        (DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=0.0.0.0)(PORT=16000)))
      Services Summary...
      Service "extproccontainer.com" has 1 instance(s).
        Instance "extproccontainer", status UNKNOWN, has 1 handler(s) for this service...
      The command completed successfully
      
      (base) [oracle@extproc-agent-170798 /]$ cd $ORACLE_HOME/network/admin
      
      (base) [oracle@extproc-agent-170798 admin]$ cat sqlnet.ora
      
      NAMES.DIRECTORY_PATH= (TNSNAMES, EZCONNECT)
      WALLET_LOCATION =(SOURCE = (METHOD = FILE)(METHOD_DATA = (DIRECTORY = /u01/app/oracle/wallets/extproc_wallet)))
      tcp.invited_nodes=(20.63.19.141,20.63.19.141,20.63.19.143,20.63.19.144)
      tcp.validnode_checking=yes
      
      (base) [oracle@extproc-agent-170798 admin]$ orapki wallet display -wallet /u01/app/oracle/wallets/extproc_wallet/cwallet.sso
      Oracle PKI Tool Release 23.0.0.0.0 - Production
      Version 23.0.0.0.0
      Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved.
      
      Requested Certificates:
      User Certificates:
      Subject:        CN=extproc-agent-170798
      Trusted Certificates:
      Subject:        CN=extproc-agent-170798
      (base) [oracle@extproc-agent-170798 admin]$ exit
      exit
      在上面的示例中,我们收集了 DBMS_CLOUD_FUNCTION.CREATE_CATALOG API 的以下输入。
      • 由 FQDN + 端口号构成的字符串将是 library_listener_url 参数的输入。在此示例中,它是 'extproc-agent-170798.subnet-name.vcn-name.oraclevcn.com:16000'。
      • sqlnet.ora 包含 wallet 文件在 VM 中的位置:/u01/app/oracle/wallets/extproc_wallet/cwallet.sso。请注意 tcp.invited_nodes 的 IP 地址列表。它必须包含您在创建 EXTPROC VM 堆栈时作为网络配置的输入提供的客户端 IP 地址列表。
      • 证书唯一判别名 (DN) 将是 library_ssl_server_cert_dn 参数的输入:'CN=extproc-agent-170798'。
  3. 构建 C 库并将其放在 EXTPROC VM 文件系统中的指定位置

    编写 C 函数代码,构建它,并将库放在 ExtProc 代理 VM 文件系统的指定目录中。

    库的名称必须与您在创建 ExtProc 堆栈期间提供的名称完全匹配。如果放错位置,可以在如下所示的 ExtProc 容器 initextproccontainer.ora 文件的 EXTPROC_DLLS 条目中找到该文件,也可以在创建 ExtProc 堆栈的 ORM (Oracle Resource Manager) 作业的“变量”部分中找到该文件。必须将库复制到 EXTPROC 代理 VM 上的 /u01/app/oracle/extproc_libs 目录。
    • 完整文件路径名(在本示例中为 "/u01/app/oracle/extproc_libs/helloCextproc.so ")将是 DBMS_CLOUD_FUNCTION.CREATE_CATALOG() 的参数 library_remote_path 的输入。
    (base) [oracle@extproc-agent-170798 client_1]$ cat $ORACLE_HOME/hs/admin/initextproccontainer.ora
    SET TRACE_LEVEL=ON
    SET _EXTPROC_REMOTE=TRUE
    SET WHOAMI=FROMDOCKER
    SET LD_LIBRARY_PATH=/u01/app/oracle/product/23.0.0.0/client_1/lib:/u01/app/oracle/extproc_libs:/opt/conda/lib
    SET EXTPROC_DLLS=ONLY:/u01/app/oracle/product/extprocutils.so:/u01/app/oracle/product/23.0.0.0/client_1/lib/libgsfextproc.so:/u01/app/oracle/extproc_libs/helloCextproc.so
    SET PYTHONHOME=/opt/conda
    SET SCRIPTS_FOLDER_LOC_ENV=/u01/app/oracle/extproc_scripts
    SET TRACE_FILE_LOC_ENV=/u01/app/oracle/extproc_logs
    SET PYTHONPATH=/tmp:/u01/app/oracle/extproc_scripts
    (base) [oracle@extproc-agent-170798 client_1]$ exit
    
    [oracle@extproc-agent-170798 ~]$ cat > helloCextproc.c
    #include <stdio.h>
    const char* helloCextproc() {
            return ("\nHello C Extproc from FQDN: extproc-agent-170798.subnet-name.vcn-name.oraclevcn.com\n");
    }
    ^D
    
    [oracle@extproc-agent-170798 ~]$ gcc -shared -fPIC -o /u01/app/oracle/extproc_libs/helloCextproc.so helloCextproc.c
    
    [oracle@extproc-agent-170798 ~]$ ls -al /u01/app/oracle/extproc_libs/
    total 8
    drwxr-xr-x. 2 oracle oinstall   30 Nov 19 11:14 .
    drwxr-xr-x. 6 root   root       91 Nov 14 02:19 ..
    -rwxr-xr-x. 1 oracle oinstall 8184 Nov 19 11:14 helloCextproc.so
    [oracle@extproc-agent-170798 ~]$

    这将完成在数据库应用程序中创建目录/库对象所需的所有参数输入。

  4. 将 wallet 文件从 ExtProc VM 上载到 OCI 对象存储

    在 EXTPROC 代理应用程序创建过程中会创建自签名 wallet。此 wallet 允许您访问 Extproc 代理实例。

    要在 EXTPROC 代理实例上执行远程过程, Autonomous AI Database 和 EXTPROC 代理使用相互传输层安全性 (mutual Transport Layer Security,mTLS) 进行连接。使用相互传输层安全 (Mutual Transport Layer Security,mTLS) 时,客户机使用带有可信客户机证书颁发机构 (Contrusted Client Certificate Authority,CA) 证书的标准 TLS 1.2 通过 TCPS(Secure TCP) 数据库连接进行连接。

    注意:

    您还可以获取并使用证书颁发机构 (Certificate Authority,CA) 颁发的公共证书。

    作为先决条件,您必须将 wallet 从运行 EXTPROC 的 VM 上的 /u01/app/oracle/extproc_wallet 目录导出到 OCI 对象存储。

    注意:

    • 保护 wallet 文件。通过 wallet 文件以及数据库用户 ID 和密码,可以访问 EXTPROC 代理实例。将钱包文件存储在安全位置,并仅与授权用户共享。
    • 请勿重命名 wallet 文件。对象存储中的 wallet 文件必须命名为 cwallet.sso
  5. 创建目录,定义 SQL 函数,并调用外部过程作为 SQL 函数

    在前面的步骤中,我们拥有 DBMS_CLOUD_FUNCTION API 执行 SQL 或 PL/SQL 数据库应用程序中的远程过程所需的所有输入。

    接下来,将包含 EXTPROC 代理实例的 wallet cwallet.sso 从对象存储导入到 Autonomous AI Database 中的 DIRECTORY。

    创建身份证明以访问存储 wallet 文件 cwallet.sso 的对象存储。有关不同对象存储服务的用户名和密码参数的信息,请参见CREATE_CREDENTIAL Procedure

    在数据库中创建一个 DIRECTORY 对象,然后使用 DBMS_CLOUD.GET_OBJECT API 将 wallet 下载到目录中。

    SQL> SET DEFINE OFF
    
    SQL> BEGIN
      DBMS_CLOUD.CREATE_CREDENTIAL (
    	credential_name => 'OCI_CREDENTIAL',
    	user_ocid       => '<oci_user_ocid>',
    	tenancy_ocid    => '<oci_tenancy_ocid>',
    	private_key     => '<API-key-dot-pem-file-contents>',
    	fingerprint     => '<fingerprint-created-with-API-key>');
    END;
    /
    
    SQL> CREATE DIRECTORY extprocwalletdir AS 'extprocwalletdir';
    
    Directory created.
    
    SQL> SELECT directory_name, directory_path FROM dba_directories WHERE directory_name LIKE '%EXTPROC%';
    
    DIRECTORY_NAME    DIRECTORY_PATH
    ----------------  -------------------------------------------------------------------------
    EXTPROCWALLETDIR  /u02/data/dbfs/<adbd-name>/42E945D608E16DF9E0630301000AF88D/extprocwalletdir
    
    SQL> BEGIN
      DBMS_CLOUD.GET_OBJECT (
      credential_name     => 'OCI_CREDENTIAL',
      object_uri          => 'https://objectstorage.us-ashburn-1.oraclecloud.com/p/aN.../n/zr.../b/bucket-name-20260129/o/cwallet.sso',
      directory_name      => 'EXTPROCWALLETDIR'
      );
    END;
    /

    接下来,使用在上一步中收集的输入参数在数据库中创建表示 ExtProc 中 C 库的库对象。

    SQL> BEGIN
      DBMS_CLOUD_FUNCTION.CREATE_CATALOG (
         library_name               => 'EXTPROC_LIBRARY',
         library_listener_url       => 'extproc-agent-170798.subnet-name.vcn-name.oraclevcn.com:16000',
         library_wallet_dir_name    => 'EXTPROCWALLETDIR',
         library_ssl_server_cert_dn => 'CN=extproc-agent-170798',
         library_remote_path        => '/u01/app/oracle/extproc_libs/helloCextproc.so'
      );
    END;
    /
    PL/SQL procedure successfully completed.
    
    SQL> SELECT catalog_name from DBA_CLOUD_FUNCTION_CATALOG WHERE catalog_name LIKE '%EXTPROC%';
    
    CATALOG_NAME
    ---------------
    EXTPROC_LIBRARY

    创建映射到 ExtProc C 函数的 SQL 函数。请参见上述程序中 C 函数的名称。

    SQL> CREATE OR REPLACE FUNCTION HELLOCEXTPROC RETURN VARCHAR2 AS
        LANGUAGE C
        LIBRARY EXTPROC_LIBRARY
        NAME "helloCextproc";
    /
    
    Function created.
    
    SQL> 

    调用 SQL 函数。这是一次成功的运行(请参见上面的 C 例程中的 C 函数的正文)。

    SQL> SELECT HELLOCEXTPROC() FROM dual;
    
    HELLOCEXTPROC()
    ----------------------------------------------------------------------------------
    Hello C Extproc from FQDN: extproc-agent-170798.subnet-name.vcn-name.oraclevcn.com