utl_http.set_transfer_timeout必须在begin_request之后、get_response之前调用,仅控制接收响应阶段超时,单位秒,需配合end_of_body异常处理和正确acl、wallet配置。

UTL_HTTP.set_transfer_timeout 必须在 get_response 前调用
超时不是全局配置,而是针对单次请求生效。很多人把 UTL_HTTP.set_transfer_timeout 放在 UTL_HTTP.begin_request 之前或 UTL_HTTP.get_response 之后,结果完全无效——Oracle 只在读取响应体时才真正启用这个值。
-
UTL_HTTP.set_transfer_timeout(120)单位是秒,建议设为 60~180,避免外部 API 偶然延迟导致 PL/SQL 卡死 - 必须紧接在
UTL_HTTP.begin_request之后、UTL_HTTP.get_response之前调用,顺序错就等于没设 - 该超时仅控制「从服务端接收数据」阶段,不包含 DNS 解析、TCP 连接建立、SSL 握手等前置耗时
读响应不加 end_of_body 异常捕获会直接报错
UTL_HTTP 读取响应体时,如果服务端提前关闭连接或返回空 body,不主动处理 UTL_HTTP.end_of_body 异常就会抛未捕获异常,整个存储过程中断,还可能漏掉关键错误信息(比如 400 Bad Request 的 JSON 提示)。
- 必须用
BEGIN ... EXCEPTION WHEN UTL_HTTP.end_of_body THEN ... END包裹UTL_HTTP.read_line或UTL_HTTP.read_text循环 - 不要依赖
UTL_HTTP.is_open(resp)判断是否可读——它返回 TRUE 并不代表还有数据,只是连接尚未显式关闭 - 每次读完一行或一段后,记得检查
UTL_HTTP.get_header_value(resp, i)获取状态码和 Content-Type,别只盯着 body
HTTPS 请求超时失败?先确认 Wallet 和证书链是否完整
ORA-29024 不是超时,而是证书校验失败;但现象常被误判为“连接超时”。Oracle 19c 默认不信任任何公共 CA,哪怕目标用的是 Let’s Encrypt,没导入对应根证书和中间证书,SSL 握手就在 1~2 秒内失败,根本走不到 transfer timeout 阶段。
- 用
orapki wallet display -wallet /path/to/wallet确认 Trusted Certificates 列表里有目标站点的签发机构(如CN=DigiCert TLS RSA SHA256 2020 CA1) -
UTL_HTTP.set_wallet('file:/path/to/wallet', 'pwd')中的路径必须是目录,不是.p12文件名;且 Oracle 进程用户(如 oracle)要有该目录的读权限 - 自签名或私有 CA 场景下,不能只导入服务器证书,必须把完整证书链(root + intermediate + server)合并为 PEM 再批量导入
Content-Length 错误导致超时假象
POST 请求中 Content-Length 设错,服务端收不到完整 body,可能直接关闭连接或返回 400,客户端却还在等响应——看起来像超时,实际是协议层错误。
- 中文 JSON body 要用
LENGTHB算字节数,不是LENGTH:例如LENGTHB(CONVERT(json_str, 'AL32UTF8', 'ZHS16GBK')) - 必须在
UTL_HTTP.write_text或UTL_HTTP.write_raw之前调用UTL_HTTP.set_header(req, 'Content-Length', ...),顺序颠倒无效 - 别用
UTL_HTTP.set_body——这个函数根本不存在,老教程写的都是错的











