oracle存储过程调用web service超时本质是底层http连接或java层阻塞未释放,utl_http默认无超时(无限等待),需显式调用set_transfer_timeout(建议30~60秒)和set_response_error_check(true),且必须在begin_request之后、write_text之前设置;utl_dbws因jvm超时不可控且已弃用,应改用utl_http手动构造soap请求,并配合网络连通性验证与connection: close头规避中间设备静默断连。
oracle存储过程调用外部web service超时,本质是底层http连接或java层阻塞未及时释放,不是简单调大timeout参数就能解决。
UTL_HTTP调用必须显式设置超时值
很多人以为 UTL_HTTP 默认有合理超时,实际它在 Oracle 10g–12c 中默认不设超时(即无限等待),一旦远端服务卡住或网络中断,整个 PL/SQL 会挂起,直到数据库资源耗尽或被 DBA kill。
-
UTL_HTTP.set_transfer_timeout控制单次读/写操作超时(单位:秒),建议设为30~60 -
UTL_HTTP.set_response_error_check应设为TRUE,否则 HTTP 4xx/5xx 状态码不会抛异常,后续read_text可能直接报错 - 必须在
utl_http.begin_request之后、utl_http.write_text之前调用超时设置,顺序错就无效 - 示例关键片段:
http_req := utl_http.begin_request('http://api.example.com/ws', 'POST'); utl_http.set_transfer_timeout(http_req, 45); utl_http.set_response_error_check(http_req, TRUE);
UTL_DBWS 调用的超时不可控,应避免使用
UTL_DBWS 是 Oracle 10g 提供的 Java-based WebService 客户端封装,但它的超时完全由 JVM 内部控制,无法通过 PL/SQL 参数调整。遇到 ORA-29532: Java 调用被未捕获的 Java 异常错误终止 时,大概率是底层 Axis 或 JAX-RPC 在解析 WSDL 或序列化时卡死,且无超时熔断机制。
- 官方已弃用该包,11g 后未更新,
loadjava加载的 jar 包(如dbwsclientdb11.jar)存在已知 serialization 兼容性问题 - 报错
getSerializer requires a Java type and/or an XML type就是典型 WSDL 解析失败后无限等待的表征 - 除非遗留系统强约束,否则应彻底放弃
UTL_DBWS,改用UTL_HTTP手动构造 SOAP 请求
网络层和防火墙导致的“伪超时”更难排查
看起来是超时,实际可能是 Oracle 数据库服务器到目标 Web Service 的 TCP 连接在中间设备(如负载均衡器、WAF、企业防火墙)上被静默断开,而 Oracle 还在等响应。
- 检查数据库服务器能否
telnet target-host port通,确认基础连通性 - 目标服务若启用了 HTTP Keep-Alive,需在请求头中明确加
Connection: close,否则 Oracle 可能复用异常连接 - 某些代理会强制 60 秒空闲超时,此时即使你设了
set_transfer_timeout(120)也无效——连接早被中间设备关了 - 可在
UTL_HTTP调用前后加DBMS_OUTPUT.PUT_LINE(SYSDATE)日志,确认是卡在 request 阶段还是 response 阶段
真正可靠的超时控制必须落在 UTL_HTTP 的 transfer timeout 上,且要配合网络层验证;任何依赖 Java 层或外部中间件的“全局超时”在 Oracle 存储过程中都不可信。最易被忽略的是:没设 set_response_error_check(TRUE) 导致 HTTP 错误码被吞,后续解析空响应体时才崩,让人误判为超时。











