news 2026/10/11 14:57:03

Oracle 计划任务配 TaoToken:DBMS_SCHEDULER 作业调用外部 API 的 Key 统一管理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Oracle 计划任务配 TaoToken:DBMS_SCHEDULER 作业调用外部 API 的 Key 统一管理

1. Oracle 计划任务调用外部 API 的密钥困境

在 Oracle 数据库里用DBMS_SCHEDULER定时跑作业,本身是很成熟的玩法:每天凌晨清理锁、同步数据、生成报表,交给数据库自己调度,省心。但一旦作业里需要调用外部 HTTP API,事情就变得别扭了——你总不能在存储过程里写死一个 API Key 吧?

我见过太多这样的脚本:DBMS_SCHEDULER作业里直接拼一个Authorization: Bearer sk-xxxx的字符串,或者把密钥塞进一张明文配置表。问题很直接:密钥轮换时,你得改存储过程、重新编译、再逐个作业确认;多个作业共用同一个 Key 时,改一处漏一处;更麻烦的是,DBA 和开发往往不是同一批人,密钥散落在各个 schema 里,审计时根本说不清谁在用哪个 Key。

这篇要解决的就是这个场景:Oracle 数据库内的DBMS_SCHEDULER定时作业需要调用外部 HTTP API,如何把 Key 从作业脚本里抽出来,做统一管理。适合已经在用 Oracle 调度、又需要对接大模型或第三方 API 的 DBA 和后台开发。核心思路是:把凭据集中放在一个地方,作业运行时动态取用,轮换时只改一处。

Oracle 本身没有原生的 HTTP 客户端,所以调用外部 API 通常靠UTL_HTTP包,或者用 Java 存储过程。无论哪种方式,密钥都不该硬编码在what参数或过程体里。下面我会给出可复制的统一 Key 配置步骤、DBMS_SCHEDULER作业创建脚本,以及一次手动RUN_JOB验证,确认作业能正常取到凭据并完成调用。

先说清楚一个前提:本文的凭据统一管理,指的是把 Key 集中存放在一个受控的配置表或外部配置源里,作业通过查询取用,而不是把 Key 写进每个作业的脚本。这样轮换时只更新一处,所有作业自动生效。

2. TaoToken 前置:统一 Key 与 Base URL 准备

要让 Oracle 作业调用外部 API,你得先有一个稳定的 API 入口和一把可管理的 Key。这里用 TaoToken 作为统一入口来演示,原因是它把模型调用收敛到一个 Base URL 和一把 Key 上,作业侧只需要认这两个值,轮换时改配置表即可,不用动存储过程。

先明确三个要素,后面所有脚本都围绕它们:

要素值说明
Base URLhttps://taotoken.net/api所有请求的根地址,作业里拼接具体路径
API Key在控制台生成形如sk-...,存配置表,不写进过程体
Model ID按需选择调用对话接口时放在请求体里

获取 Key 的入口在控制台的 API Keys 页面,登录后新建一个 Key,复制出来。注意:Key 只在创建时完整显示一次,务必当场保存到你的密码管理工具或直接写入下面的配置表。

  • 控制台入口:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite
  • API Keys 页面:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite
  • 接入文档:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite

如果你只是想先验证模型能不能通,可以用模型对话页面手动发一条请求,确认 Key 有效、Base URL 可达,再回到数据库侧配置。这一步能帮你排除「到底是网络问题还是脚本问题」。

  • 模型对话:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite

对于长期跑编码类或 Agent 类作业的场景,可以考虑 Coding Plan,它更适合高频、持续的调用,配额和计费方式对定时任务更友好。但本文的重点是「作业如何取到凭据」,所以先用普通 Key 把链路跑通。

  • Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite

关键点在于:Oracle 作业不直接持有 Key,而是从配置表读取。配置表里存 Base URL、Key、Model ID,作业运行时SELECT出来拼进请求。这样轮换 Key 时,你只UPDATE一行,所有引用该配置的作业下次执行自动用新 Key。

3. 可复制配置:配置表 + 存储过程 + 作业脚本

这一节是全文的核心,全部可复制。分三步:建配置表、写取凭据并调用的存储过程、创建DBMS_SCHEDULER作业。

3.1 建统一凭据配置表

先建一张配置表,存放 Base URL、Key、Model ID。用单独的表而不是写死在过程里,是轮换友好的前提。

-- 以当前 schema 为例,生产环境建议放独立 schema 并授权 CREATE TABLE api_credential ( cred_name VARCHAR2(64) PRIMARY KEY, base_url VARCHAR2(256) NOT NULL, api_key VARCHAR2(512) NOT NULL, model_id VARCHAR2(128) NOT NULL, updated_at TIMESTAMP DEFAULT SYSTIMESTAMP ); -- 插入 TaoToken 的统一凭据 INSERT INTO api_credential (cred_name, base_url, api_key, model_id) VALUES ( 'TAOTOKEN_DEFAULT', 'https://taotoken.net/api', 'sk-你的实际Key', '你的模型ID' ); COMMIT;

注意两点:一是api_key字段长度给足,Key 可能较长;二是这张表要限制访问权限,只给作业所属 schema 读权限,别让普通账号随便查。

3.2 写取凭据并调用 API 的存储过程

Oracle 调用 HTTP 用UTL_HTTP。下面这个存储过程做三件事:从配置表取凭据、拼 JSON 请求体、发 POST 请求并读回响应。为了演示清晰,请求体里放一个简单 prompt。

CREATE OR REPLACE PROCEDURE call_taotoken_api ( p_prompt IN VARCHAR2 ) AS l_base_url VARCHAR2(256); l_api_key VARCHAR2(512); l_model_id VARCHAR2(128); l_req UTL_HTTP.req; l_resp UTL_HTTP.resp; l_body CLOB; l_buffer VARCHAR2(32767); l_response CLOB := ''; BEGIN -- 1. 从配置表取统一凭据 SELECT base_url, api_key, model_id INTO l_base_url, l_api_key, l_model_id FROM api_credential WHERE cred_name = 'TAOTOKEN_DEFAULT'; -- 2. 拼 JSON 请求体 l_body := '{"model":"' || l_model_id || '",' || '"messages":[{"role":"user","content":"' || p_prompt || '"}]}'; -- 3. 发起 POST 请求 l_req := UTL_HTTP.begin_request( url => l_base_url || '/v1/chat/completions', method => 'POST', http_version => UTL_HTTP.http_version_1_1); UTL_HTTP.set_header(l_req, 'Content-Type', 'application/json'); UTL_HTTP.set_header(l_req, 'Authorization', 'Bearer ' || l_api_key); UTL_HTTP.set_header(l_req, 'Content-Length', TO_CHAR(LENGTHB(l_body))); UTL_HTTP.write_text(l_req, l_body); -- 4. 读响应 l_resp := UTL_HTTP.get_response(l_req); BEGIN LOOP UTL_HTTP.read_text(l_resp, l_buffer, 32767); l_response := l_response || l_buffer; END LOOP; EXCEPTION WHEN UTL_HTTP.end_of_body THEN NULL; END; UTL_HTTP.end_response(l_resp); -- 5. 落库或打印,这里简单插入日志表 INSERT INTO api_call_log (called_at, prompt, response) VALUES (SYSTIMESTAMP, p_prompt, l_response); COMMIT; EXCEPTION WHEN OTHERS THEN -- 记录失败,便于排查 INSERT INTO api_call_log (called_at, prompt, response) VALUES (SYSTIMESTAMP, p_prompt, 'ERROR: ' || SQLERRM); COMMIT; RAISE; END; /

配套的日志表:

CREATE TABLE api_call_log ( id NUMBER GENERATED ALWAYS AS IDENTITY, called_at TIMESTAMP, prompt VARCHAR2(4000), response CLOB );

这里的关键设计是:存储过程只认cred_name,不认具体 Key。轮换时UPDATE api_credential SET api_key = '新Key' WHERE cred_name = 'TAOTOKEN_DEFAULT',过程一行不用改。

3.3 创建 DBMS_SCHEDULER 作业

现在把存储过程挂到DBMS_SCHEDULER上,设定每天执行一次。相比老的DBMS_JOB,DBMS_SCHEDULER的调度表达式更清晰,也支持更细的权限控制。

BEGIN DBMS_SCHEDULER.create_job ( job_name => 'JOB_CALL_TAOTOKEN', job_type => 'PLSQL_BLOCK', job_action => 'BEGIN call_taotoken_api(''每日健康检查''); END;', start_date => SYSTIMESTAMP, repeat_interval => 'FREQ=DAILY; BYHOUR=2; BYMINUTE=0; BYSECOND=0', enabled => TRUE, comments => '每日调用 TaoToken API,凭据来自 api_credential' ); END; /

如果你更习惯用DBMS_JOB的写法,等价形式是:

DECLARE x NUMBER; BEGIN SYS.DBMS_JOB.SUBMIT( job => x, what => 'call_taotoken_api(''每日健康检查'');', next_date => SYSDATE, interval => 'SYSDATE + 1', no_parse => FALSE ); COMMIT; END; /

两种方式都能跑,但新项目建议用DBMS_SCHEDULER,它的repeat_interval用日历语法,比SYSDATE + 1/1440这种算术表达式可读性好得多。

3.4 网络权限配置

UTL_HTTP默认可能没有外网访问权限,需要给作业所属用户授权。用DBMS_NETWORK_ACL_ADMIN配置访问控制列表:

BEGIN DBMS_NETWORK_ACL_ADMIN.create_acl ( acl => 'taotoken_acl.xml', description => 'Allow access to TaoToken API', principal => 'YOUR_SCHEMA', is_grant => TRUE, privilege => 'connect', start_date => SYSTIMESTAMP, end_date => NULL ); DBMS_NETWORK_ACL_ADMIN.assign_acl ( acl => 'taotoken_acl.xml', host => 'taotoken.net', lower_port => 443, upper_port => 443 ); COMMIT; END; /

把YOUR_SCHEMA换成实际作业所属的 schema 名。这一步不做,UTL_HTTP会直接抛网络访问被拒的错。

4. 验证请求:手动 RUN_JOB 与结果确认

配置写完不能直接等定时触发,先手动跑一次,确认凭据取得到、请求发得出、响应回得来。

4.1 手动执行作业

BEGIN DBMS_SCHEDULER.run_job('JOB_CALL_TAOTOKEN', use_current_session => TRUE); END; /

use_current_session => TRUE让作业在当前会话同步执行,方便你立刻看到结果和异常。如果省略这个参数,作业会异步跑,你得去查日志表。

4.2 确认凭据被正确取用

先确认配置表里的值没问题:

SELECT cred_name, base_url, model_id, updated_at FROM api_credential WHERE cred_name = 'TAOTOKEN_DEFAULT';

再查调用日志,看响应是否落库:

SELECT id, called_at, SUBSTR(response, 1, 200) AS resp_head FROM api_call_log ORDER BY id DESC FETCH FIRST 5 ROWS ONLY;

如果response里能看到模型返回的内容,说明整条链路通了:作业触发 → 存储过程执行 → 从配置表取 Key → 发 HTTP 请求 → 响应落库。

4.3 查看作业执行历史

DBMS_SCHEDULER有内置的作业运行视图,能看每次执行的状态和耗时:

SELECT job_name, status, actual_start_date, run_duration FROM user_scheduler_job_run_details WHERE job_name = 'JOB_CALL_TAOTOKEN' ORDER BY actual_start_date DESC FETCH FIRST 10 ROWS ONLY;

status为SUCCEEDED就说明作业本身执行成功。如果失败,additional_info字段里通常有错误堆栈,这是排查的第一手资料。

4.4 验证轮换是否生效

这是统一管理的关键验证:改一次配置表,确认作业自动用新 Key。

UPDATE api_credential SET api_key = 'sk-新的Key', updated_at = SYSTIMESTAMP WHERE cred_name = 'TAOTOKEN_DEFAULT'; COMMIT; -- 再跑一次作业 BEGIN DBMS_SCHEDULER.run_job('JOB_CALL_TAOTOKEN', use_current_session => TRUE); END; /

如果新 Key 有效,日志表里会新增一条成功记录;如果新 Key 无效,会记录ERROR: ORA-...或 HTTP 401 相关信息。整个过程存储过程一行没改,这就是把 Key 抽出来的价值。

5. 本篇常见错排查

这一节按真实报错来,遇到问题直接对号入座。

5.1 ORA-29273 / network access denied

报错形如:

ORA-29273: HTTP request failed ORA-06512: at "SYS.UTL_HTTP", line ... ORA-24247: network access denied by access control list (ACL)

原因:UTL_HTTP没有访问taotoken.net的 ACL 授权。回到 3.4 节,确认assign_acl里的 host 是taotoken.net、端口是 443,且 principal 是作业实际所属的 schema。注意 schema 名大小写要和数据库里一致,Oracle 默认大写。

5.2 HTTP 401 Unauthorized

日志表里response出现 401,说明请求发出去了,但 Key 不对。排查顺序:

  • 配置表里的api_key是否完整,有没有多余空格或换行;
  • 请求头是不是Authorization: Bearer sk-...,Bearer和 Key 之间一个空格;
  • Key 是否已在控制台被删除或过期。

对照检查请求头拼接:

UTL_HTTP.set_header(l_req, 'Authorization', 'Bearer ' || l_api_key);

如果l_api_key里带了换行,拼接后请求头会断,服务端解析失败。可以在取凭据后加一句l_api_key := TRIM(l_api_key);。

5.3 ORA-29268 / peer certificate

报错形如:

ORA-29268: HTTP client error occurred ORA-29024: Certificate validation failure

这是 HTTPS 证书校验问题。Oracle 的UTL_HTTP走 HTTPS 需要钱包(wallet)配置,或者确认数据库版本对目标证书链的支持。生产环境建议正确配置 wallet,而不是简单关掉校验。如果只是内网测试,可以临时用UTL_HTTP.set_wallet指定钱包路径。

5.4 响应读取不完整 / reading choices 类解析问题

如果日志里response被截断,或者你后续要解析 JSON 里的choices字段,注意UTL_HTTP.read_text是按块读的,必须循环读到end_of_body。3.2 节的循环写法就是为此。另外VARCHAR2最大 32767 字节,响应较长时要用CLOB拼接,别用VARCHAR2存整个响应。

如果你在应用侧(比如 Java、Python)解析响应时报reading choices相关错误,通常是响应体不是预期的 JSON 结构——先看日志表里原始响应长什么样,再决定怎么解析。

5.5 作业状态 FAILED 但日志表无记录

如果user_scheduler_job_run_details显示 FAILED,但api_call_log里没有对应记录,说明失败发生在进入存储过程之前,或者异常处理没覆盖到。检查:

  • job_action里的 PL/SQL 块语法是否正确,字符串引号有没有转义;
  • 作业所属 schema 对api_credential和api_call_log有没有读写权限;
  • 存储过程是否编译通过,SELECT * FROM user_errors WHERE name = 'CALL_TAOTOKEN_API'查编译错误。

5.6 轮换后仍用旧 Key

改了配置表但作业还用旧 Key,最常见原因是存储过程里用了SELECT ... INTO但没重新查,或者你在过程里做了缓存。本文的写法每次执行都重新SELECT,所以不会缓存。如果你自己改成了包变量缓存,记得在轮换后重置包状态,或者干脆别缓存。

另一个可能是COMMIT没执行,UPDATE还在事务里没落库,作业在另一个会话读不到。确认UPDATE后COMMIT。

6. 把凭据管理收口到一处

回到最初的问题:Oracle 计划任务调用外部 API,密钥硬编码在作业脚本里,轮换困难。本文的做法是把 Base URL、Key、Model ID 收进一张配置表,存储过程按cred_name取用,DBMS_SCHEDULER作业只负责触发。轮换时UPDATE一行,所有作业下次执行自动生效。

几个实操建议:

第一,配置表放独立 schema,只给作业 schema 读权限,别让业务账号能查 Key。第二,api_call_log定期清理,避免日志表无限膨胀,可以用另一个DBMS_SCHEDULER作业做归档。第三,Key 轮换后主动跑一次run_job验证,别等凌晨定时触发才发现问题。第四,如果作业调用频率高,考虑用 Coding Plan 这类更适合持续调用的方案,配额和成本更可控。

如果你还没拿到 Key,先去控制台建一个,把 Base URL 和 Key 填进api_credential表,然后按第 4 节手动跑一次。链路通了,再交给定时器。接入细节和参数说明在文档里,遇到报错先对照第 5 节。

  • API Keys:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite
  • 接入文档:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite
  • 模型对话验证:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite
  • Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/11 14:56:35

双节完成近2000万次服务任务,酒店该重新算“机器人+AI”这笔账了

作者 | Tniniuo编辑 | Sette01.节假日洪峰,酒店老板最怕的不是满房,是满房后接不住的电话酒店这生意,节奏很特别。平日入住率相对平稳,一到节假日,需求却可能瞬间翻倍。酒店人盼着满房,可真正满房时&#x…

作者头像 李华
网站建设 2026/10/11 14:56:01

PCB缺陷检测:6930张增强图像与YOLOv8训练全流程解析

简介:PCB板缺陷检测数据集源自北京大学,面向工业质检与深度学习目标检测场景,可帮助研究者和算法工程师解决线路板表面缺陷样本稀缺、标注成本高的问题。包体共1346个文件,容量约584MB,含445张jpg缺陷图像及对应完整的…

作者头像 李华
网站建设 2026/10/11 14:53:47

FaceNet人脸特征提取与工业级部署实战

简介:本资源是一份面向人工智能与深度学习初学者的FaceNet人脸识别实践项目,聚焦计算机视觉中的核心任务——人脸验证与识别,适用于高校学生、转行学习者及算法工程师快速掌握深度度量学习原理与工程实现。压缩包共10个文件,含3个…

作者头像 李华