我在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上下文。
2条答案
按热度按时间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 在带有异常处理程序的匿名块中:
字符串
1.对于去往/来自客户端和去往/来自数据库链路的正常网络流量,
v$sesstat
中也有会话统计信息,提供了去往/来自这两个源的字节数。但我不相信TCP套接字通过UTL_TCP
及其更高级别的包,如UTL_HTTP
,UTL_SMTP
等。是如此的仪器化。我的数据表明,没有任何v$sesstat
统计数据可以跟踪流量。当然,你可以在操作系统上放置一个监视shell脚本,每分钟运行一次netstat
,然后在系统级收集TCP统计数据,但你当然无法区分应用程序的工作和其他使用网络的任何东西。您可以在http请求之前和之后使用SYSTIMESTAMP
,同时获取每个响应的LENGTH
,并创建您自己的度量来从过程内部监控吞吐量。dl5txlt92#
我建议跟踪成功处理的行。有时敏感数据不应该被处理两次。
例如,在表PAYMENTS中,您可以在循环中添加一个名为PROCESSED的列,并且每当一行正确完成时,您可以执行以下操作:
字符串
并且Cursor也应该被更改为不考虑已经处理的行。
型
如果你这样做,每当程序因网络问题或其他原因失败时: