Windows Server下Oracle调用外部程序的配置故障与方案咨询
Oracle调用外部程序手动触发失败排查与实现方案
问题背景
需求为实现Oracle数据库调用外部程序,最终目标是通过触发器触发调用,当前优先验证手动调用的可用性,已完成的配置操作如下:
- 创建测试批处理文件
C:\TEMP\printline.bat,功能为打印提示文本,文件内容:
@echo off echo Oracle call done !! pause
- 执行PL/SQL创建调度程序,执行完成后可在
DBA_SCHEDULER_PROGRAMS表中查询到对应记录:
BEGIN DBMS_SCHEDULER.CREATE_PROGRAM ( program_name => 'TEST_EXE', program_type => 'EXECUTABLE', program_action => 'C:\TEMP\printline.bat', enabled => TRUE ); END; /
- 未找到直接运行已注册程序的
DBMS_SCHEDULER.RUN_PROGRAM类命令,确认需通过Job(作业)实现外部程序调用,先后用两种方式创建作业:- 关联已创建的
TEST_EXE程序
BEGIN DBMS_SCHEDULER.CREATE_JOB ( job_name => 'TEST_EXE_JOB', program_name => 'TEST_EXE', enabled => TRUE, repeat_interval => 'freq=yearly', start_date => SYSDATE); END; /- 直接指定作业类型为可执行文件,指向目标bat文件
注:将重复间隔设置为年频是因为仅需要手动触发作业运行,begin dbms_scheduler.create_job ( job_name => 'TEST_EXE_JOB', job_type => 'EXECUTABLE', job_action => 'C:\TEMP\printline.bat', enabled => true, repeat_interval => 'freq=yearly', start_date => SYSDATE); end; /repeat_interval设为NULL时作业无法创建成功。 - 关联已创建的
- 执行手动运行作业命令:
begin dbms_scheduler.run_job (job_name => 'TEST_EXE_JOB'); end; /
执行后Oracle提示PL/SQL调用成功,查询DBA_SCHEDULER_JOB_RUN_DETAILS表也存在调用成功的日志,但服务器端bat文件并未实际执行。
- 配置过程中确认必须启动Windows服务
OracleJobSchedulerORCL作业调用才不会报错,未启动该服务时会抛出如下错误:
ORA-27370: échec du lancement d'un travail de type EXECUTABLE par le travail esclave ORA-27300: opération dépendante du système d'exploitation : échec de accessing job scheduler service avec l'état 2 ORA-27301: message d'erreur du système d'exploitation : The system cannot find the file specified. ORA-27302: une erreur s'est produite à : sjsec 5 ORA-27303: informations supplémentaires : The system cannot find the file specified. ORA-06512: à "SYS.DBMS_ISCHED", ligne 231 ORA-06512: à "SYS.DBMS_SCHEDULER", ligne 568 ORA-06512: à ligne 2 27370. 00000 - "job slave failed to launch a job of type EXECUTABLE" *Cause: The scheduler ran into an error when the job slave tried to start a job of type EXECUTABLE. The rest of the error stack will provide more detailed information on what the exact problem was. *Action: Correct the problem specified in the error stack and reschedule the job.
- 已知
{ORA_HOME}\rdbms\admin\externaljob.ora文件用于管理外部程序调用权限,但未找到清晰的配置规则说明。
待解决疑问
- 为什么必须通过作业+重复频率的方式实现外部程序调用?是否存在直接手动调用已注册程序的方法?
- Oracle提示作业调用成功,但bat文件未按预期执行,是否遗漏了权限配置或其他必要设置?
- 是否存在更简便的方式实现Oracle调用外部程序的需求?
问题解答
1. 作业调用的设计逻辑与无重复频率的手动触发方法
DBMS_SCHEDULER的设计逻辑里,Program(程序)只是可执行对象的定义模板,本身不具备独立运行的能力,必须绑定到Job这个执行载体上才能触发。
你之前设置年频绕手动触发完全没必要,创建一次性临时作业即可:创建时设置auto_drop => TRUE,不需要指定repeat_interval,作业运行完成后会自动删除,不会残留调度任务,创建示例:
BEGIN DBMS_SCHEDULER.CREATE_JOB ( job_name => 'TEST_EXE_JOB_ONCE', job_type => 'EXECUTABLE', job_action => 'C:\TEMP\printline.bat', enabled => FALSE, auto_drop => TRUE ); END; /
需要运行时直接调用dbms_scheduler.run_job('TEST_EXE_JOB_ONCE')即可。不存在直接跳过Job运行Program的官方方法,所有外部程序调用最终都要通过Job作为执行入口。
2. 作业显示成功但bat未执行的核心排查点
Windows环境下该问题90%以上是权限、运行身份、交互模式的问题:
- 首先修改
%ORA_HOME%\rdbms\admin\externaljob.ora配置:找到run_user和run_password参数,取消注释,设置为Windows服务器上有本地执行权限的用户(测试阶段可直接用本地管理员账号),同时将set_user参数设为TRUE。修改完成后重启OracleJobSchedulerORCL服务生效。 - 检查
OracleJobSchedulerORCL服务的登录身份:默认该服务可能用本地系统账号运行,要改成和externaljob.ora里配置的一致的账号,确保该账号对C:\TEMP目录、目标bat文件有读取和执行权限。 - 你的测试bat里加了
pause命令,Oracle调度作业是后台无交互运行,pause会导致进程挂起等待输入,且Oracle调度的外部程序运行在Windows会话0隔离桌面,即使执行成功也不会弹出可见的cmd窗口。测试时先把pause删掉,把输出重定向到日志文件验证执行结果,比如把bat内容改成:
运行作业后检查@echo off echo Oracle call done !! > C:\TEMP\test_log.txtC:\TEMP\test_log.txt是否生成,就能判断程序是否实际执行。不要用弹出窗口、需要交互的程序做测试,所有输出必须写文件才能验证。
3. 更简便的外部程序调用方案
如果是触发器触发场景,DBMS_SCHEDULER配置繁琐且权限限制多,可根据场景选择其他方案:
- 轻量场景可以用Oracle的Java存储过程+
Runtime.getRuntime().exec()方法实现外部程序调用,配置好Oracle JVM权限后可以直接在PL/SQL里调用,不需要额外启动调度服务,触发器里直接调用存储过程即可。 - 生产环境更推荐解耦实现:不要让Oracle直接调用外部程序,通过触发器往专用队列表写记录,部署独立的外部程序轮询队列表执行对应逻辑,稳定性和可维护性远高于Oracle直接调外部程序,也不会因为外部程序执行失败、挂起导致数据库事务阻塞。
内容的提问来源于stack exchange,提问作者JCB
相关产品推荐
相关产品推荐

