oracle 具有多个HTTP请求的PL/SQL过程片段的性能和含义

4uqofj5v  于 2023-08-03  发布在  Oracle
关注(0)|答案(2)|浏览(117)

我在Oracle数据库中有一个PL/SQL过程,它使用游标处理来自“PAYMENTS”表的数据,并向外部API执行HTTP请求以检索XML形式的相关数据。然后,该过程分析XML并将数据保存到另一个表中。下面是代码的简化版本:

CREATE OR REPLACE PROCEDURE ... IS
  CURSOR TRANSACTIONS IS SELECT ... FROM PAYMENTS WHERE ...
  C1 TRANSACTIONS%ROWTYPE;
  URL VARCHAR2(...);
  L_XMLTYPE ...
BEGIN
  URL := 'http://...'
   
  OPEN TRANSACTIONS;
  
  LOOP -- COULD BE 10000 ROWS OR MANY MORE
    FETCH TRANSACTIONS INTO C1;
    EXIT WHEN C%NOTFOUND;  
      
    MY_SCHEMA.MY_PACKAGE.MAKE_HTTP_REQUEST_TO_API(URL, C1.ID, RESPONSE_XML);

    -- PARSE RESPONSE XML
    L_XMLTYPE := XMLTYPE(LV_RESPONSE_DATA);

    SELECT
       EXTRACTVALUE(L_XMLTYPE, ...) AS ...
       ...
       INTO ...
    FROM DUAL;

    -- SAVE DATA FROM RESPONSE XML

    INSERT ...

  END LOOP;
        
  CLOSE TRANSACTIONS;
END;

字符串
我想了解此程序的潜在性能影响以及任何其他相关考虑如何衡量它们?
因为该过程发出HTTP请求并在继续下一行之前等待响应。可能会出现哪些具体问题?
注意:API的设计是返回每行的数据,不能更改。
我已经找到了像wireshark这样的工具来测量网络问题,但我仍然不知道如何有效地使用它。我读过关于异步和同步http调用以及主线程如何被阻塞的文章。我不确定它如何应用于Oracle上下文。

bttbmeg0

bttbmeg01#

1.网络呼叫很容易被防火墙或网络阻止软件或路由问题阻止,并且永远不会返回。您可能希望对此进行测试,以查看sqlnet超时是否有效,但即使有效,也不能完全信任。我见过很多孤立的会话在外部网络呼叫中丢失。这将导致无限期地挂起锁、撤消和其他资源。您可能希望有一个单独的异步监视器进程来检测这个问题,如果进程卡住了,就终止进程。
1.当Oracle等待http请求返回时,它会将其事件报告为TCP Socket (KGAS)。您可以在v$session中查看当前等待的会话,或在ASH(v$active_session_history)中查看过去的会话。您可以对v$session进行采样,也可以在ASH中使用Oracle自己的1秒采样(按等待事件分组),以查看过程在网络上等待的时间与在CPU和数据库内部的其他工作。
1.只要存在对Oracle数据库外部的异构事物的依赖性(如网络调用),就不建议在这些外部调用之间保持事务打开。如果你被孤立了,或者外部代理需要很长时间才能响应,你可能会无限期地阻止其他代理。我建议在循环中添加一个COMMIT,正好在INSERT之后。如果您需要事务控制,以便错误应该回滚 * 所有 * 插入(我猜不太可能),那么一个安全的解决方案是使用临时表,随时提交,然后您可以在最终表中执行单个INSERT SELECT
1.在外部调用之间尽可能少地执行本地工作也是明智的,这样您就可以尽快摆脱对远程源的依赖。Oracle数据库之间的数据库链接也是如此。网络故障的概率会提高代码中这部分的风险级别,因此您希望快速使用网络,然后完成它。尝试将任何繁重的本地工作推迟到以后,这样它就不会再受到网络问题的影响。
1.考虑添加异常处理。如果http请求(或XML解析)失败并引发某种异常,您是希望整个程序中止,还是希望记录它并转移到下一条记录并处理有效的内容?如果是后者,则需要将调用 Package 在带有异常处理程序的匿名块中:

LOOP
  BEGIN
    // http call
    // XML parse
    // something else that could fail

    COMMIT;
  EXCEPTION
    WHEN OTHERS THEN
      NULL; -- here you may log the error and the record that caused it. the loop will continue without aborting
  END;
END LOOP;

字符串
1.对于去往/来自客户端和去往/来自数据库链路的正常网络流量,v$sesstat中也有会话统计信息,提供了去往/来自这两个源的字节数。但我不相信TCP套接字通过UTL_TCP及其更高级别的包,如UTL_HTTPUTL_SMTP等。是如此的仪器化。我的数据表明,没有任何v$sesstat统计数据可以跟踪流量。当然,你可以在操作系统上放置一个监视shell脚本,每分钟运行一次netstat,然后在系统级收集TCP统计数据,但你当然无法区分应用程序的工作和其他使用网络的任何东西。您可以在http请求之前和之后使用SYSTIMESTAMP,同时获取每个响应的LENGTH,并创建您自己的度量来从过程内部监控吞吐量。

dl5txlt9

dl5txlt92#

我建议跟踪成功处理的行。有时敏感数据不应该被处理两次。
例如,在表PAYMENTS中,您可以在循环中添加一个名为PROCESSED的列,并且每当一行正确完成时,您可以执行以下操作:

update PAYMENTS set processed = 1 where id = something;
commit; -- This is very important. You may need to add (pragma autonomous_transaction)

字符串
并且Cursor也应该被更改为不考虑已经处理的行。

CURSOR TRANSACTIONS IS SELECT ... FROM PAYMENTS WHERE PROCESSED = 0 and ...


如果你这样做,每当程序因网络问题或其他原因失败时:

  • 你不会“失去”已经做过的事情;
  • 您不从0重新启动处理;
  • 如果这些数据是敏感的,您不会对任何行进行两次处理;

相关问题