不能直接并发执行p1/p2/p3,因单个job内BEGIN p1; p2; p3; END仍为串行;真并发需三个独立job,用DBMS_SCHEDULER.GENERATE_JOB_NAME确保唯一性,start_date设SYSTIMESTAMP并enabled=>TRUE,通过USER_SCHEDULER_RUNNING_JOBS验证session_id不同即可确认并行。

不能直接“并发执行”,但能通过创建多个独立 job 实现逻辑并发——关键在 job_name 唯一性、start_date 一致、不互相阻塞。
为什么不能用单个 job 并发跑 p1/p2/p3?
DBMS_SCHEDULER 的每个 job 是串行执行单元:写 BEGIN p1; p2; p3; END; 仍是顺序调用,耗时叠加。真并发必须让三个过程在不同会话中同时运行,而唯一可靠路径就是启动三个彼此无关的 job。
- job 之间默认无依赖、无锁竞争(除非存储过程内部显式加锁或争抢同资源)
- 所有 job 都设
start_date => SYSTIMESTAMP,Oracle 会尽力在毫秒级内触发,效果接近并发 - 别用
auto_drop => TRUE除非确认过程极快且无需查日志;失败时 job 会被禁用,但保留记录可查
怎么写三个并行 job?用 generate_job_name 最省事
手动拼 job_name 容易重复报 ORA-27477,DBMS_SCHEDULER.GENERATE_JOB_NAME 自动产出唯一名,适合临时/批量场景:
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => DBMS_SCHEDULER.GENERATE_JOB_NAME('P1_'),
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN p1; END;',
start_date => SYSTIMESTAMP,
enabled => TRUE,
auto_drop => FALSE
);
DBMS_SCHEDULER.CREATE_JOB(
job_name => DBMS_SCHEDULER.GENERATE_JOB_NAME('P2_'),
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN p2; END;',
start_date => SYSTIMESTAMP,
enabled => TRUE,
auto_drop => FALSE
);
DBMS_SCHEDULER.CREATE_JOB(
job_name => DBMS_SCHEDULER.GENERATE_JOB_NAME('P3_'),
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN p3; END;',
start_date => SYSTIMESTAMP,
enabled => TRUE,
auto_drop => FALSE
);
END;
- 前缀
'P1_'确保生成名可读,比如P1_1234567890 - 必须显式写
auto_drop => FALSE(默认是FALSE,但显式写更安全) - 别漏
enabled => TRUE,否则 job 创建后是 DISABLED 状态,不会跑
并发后怎么确认它们真在同时跑?
查 USER_SCHEDULER_RUNNING_JOBS 视图,不是 USER_SCHEDULER_JOBS —— 后者只存定义,前者才反映实时会话:
SELECT job_name, session_id, running_instance, elapsed_time FROM USER_SCHEDULER_RUNNING_JOBS WHERE job_name LIKE 'P%';
- 只要返回三行,且
session_id不同,就说明三个会话正在并行执行 -
elapsed_time接近说明启动时间一致;若某一个明显滞后,可能是该过程内部有锁等待或资源争用 - 如果只看到一行,检查是否某个 job 因异常被自动禁用(查
USER_SCHEDULER_JOB_LOG的STATUS = 'FAILED')
带参数的存储过程怎么并行?必须用 PLSQL_BLOCK 包裹
想并发跑 proc_sync('20261025') 和 proc_sync('20261026')?STORED_PROCEDURE 类型不支持传参,硬写会报 ORA-27469。唯一办法是:
- 每个 job 单独用
PLSQL_BLOCK,把参数写死或用函数动态生成 - 例如:
job_action => 'BEGIN proc_sync(''20261025''); END;'(注意单引号要双写) - 如果参数需每次计算(如取昨天日期),写成:
'BEGIN proc_sync(TO_CHAR(SYSDATE-1, ''YYYYMMDD'')); END;'—— 这个表达式在每次 job 执行时重算,不是建 job 时快照 - 别试图复用同一个 job 改参数:
SET_JOB_ARGUMENT_VALUE只对 PROGRAM 类型生效,不适用于直接 CREATE_JOB
真正要注意的是资源上限——Oracle 默认并发 job 数受 job_queue_processes 参数限制(通常为 1000),但实际并发度还取决于系统 CPU、PGA 和存储过程自身是否主动 sleep 或锁表。跑之前先看 V$RESOURCE_LIMIT 里 jobs 的 CURRENT_UTILIZATION,别堆到临界点再排查超时。











