【问题标题】:When an Oracle Scheduled Job is Enabled, is it run in separate session?启用 Oracle 计划作业后,它是否在单独的会话中运行?
【发布时间】:2016-10-13 00:34:04
【问题描述】:

我最近一直在学习使用 Oracle 的调度程序来异步运行作业。

我正在尝试构建只运行一次然后自动删除的作业。

我完成此操作的方法是将作业的 MAX_RUNS 属性设置为 1,并将 AUTO_DROP 属性设置为 TRUE。

默认情况下我的所有作业都被禁用,因为我只是手动启动它们。

我注意到这些工作没有被删除,这个Ask Tom thread 解释了原因。

因此,如果要自动删除它们,我必须在运行它们之前先启用它们。

但是,当启用作业时,它会立即安排。

我的问题是:

当一个计划的作业被启用并因此被立即安排时,它会在单独的会话中执行吗?

我需要异步安排所有作业,因此我希望实现与以下相同的行为:

DBMS_SCHEDULER.RUN_JOB(V_JOB_NAME, FALSE);

FALSE 表示在单独的会话中异步调度作业。

我对启用作业并立即安排它的方法很好,只要它在单独的会话中是异步的。

或者,如果有一种方法可以强制在启用时不安排作业,那也可以。

我目前使用的是 Oracle 11gR2

【问题讨论】:

    标签: oracle oracle11gr2


    【解决方案1】:

    如果我有一堆需要运行的异步 1-time 作业,我会认真考虑使用旧的 dbms_job 包而不是 dbms_scheduler 来进行调度。那么你只是在做这样的事情

    declare
      l_jobno pls_integer;
    begin
      dbms_job.submit( l_jobno,
                       '<<what you want the job to do>>',
                       sysdate );
    end;
    /
    

    这将导致在您提交运行您指定的任何代码的submit 后立即打开一个新会话。它会运行一次,然后从dba_jobs 中删除。

    或者,我会尝试重新构建系统,以便有一个后台“小部件处理器”作业每隔几分钟运行一次,读取表格以确定需要处理哪些小部件,然后处理这些小部件。这可能比生成一个单独的作业来处理每个小部件更有意义。

    dbms_scheduler 非常适合当您想要进行更复杂的处理时,其中一项作业依赖于另一项作业并且作业根据事件开始。但是,当您只需要一个非常轻量级的框架来完成非常简单的工作时,老式的 dba_jobs 会非常方便。

    【讨论】:

    • 谢谢贾斯汀,这很有意义。我的用例主要是动态数据提取。每个计划的作业只需调用一个带有 2 个参数、函数名称和客户 ID 的程序。该作业执行函数以提取数据并将数据写入文件。还有一些其他步骤,但这是主要部分。也许使用标准作业是一种更简单的方法。我计划围绕流程建立更多控制,因此可以重新启动失败的作业等,我认为这仅适用于预定的作业?非常感谢您的洞察力,再次感谢!
    • @rcurrie - 我更希望有一个表,其中包含两列命名为 customer_to_extract 之类的名称,您的代码将写入一行,然后执行一个每 n 分钟运行一次并处理所有内容的客户提取作业该表比运行一堆独立作业。这往往使构建作业控制变得更加容易(即尝试处理一行两次,如果失败,将其写入一个单独的问题提取表,有人可以监控,很容易编写一个显示提取的报告目前正在排队等)
    • 这也是一个很好的方法。之前的过程是完全同步的(每个客户执行 240 多个函数),我试图通过异步启动客户的工作来获得更好的性能。每个功能负责一个数据元素,因此如果需要处理 5 个客户,则将运行 1,200 个作业。如果客户的一项工作失败了,我希望能够重新运行那一项工作,而不是一切。希望这是有道理的。
    • @rcurrie - 我绝对不想运行 1200 个单独的作业。我宁愿有一个单独的工作来完成数据提取(如果您需要更多线程来跟上,也许其中一些)知道如何将customer_to_extract 表中的一行标记为失败。查询、修复失败的地方,然后标记该行以重试要容易得多。
    • 再次感谢您的洞察力,我一定会重新评估该过程。我很难理解如何以更少的作业运行来实现更高的吞吐量。如果作业正在调用函数来执行查询和写出数据,如果只有 1 个作业负责,那么如何同时进行多个函数调用?
    【解决方案2】:

    我发现如果将新作业的 START_DATE 设置为未来的日期,并将 REPEAT_INTERVAL 设置为类似“FREQ=YEARLY”的内容,则启用该作业时不会立即运行。

    虽然不理想,但这将允许在通过 DBMS_SCEHDULER.RUN_JOB(V_JOB_NAME, FALSE); 手动运行时删除作业。命令。

    但是,这确实意味着该作业计划在未来的某个时间运行。所以不要忘记手动运行它。在我的情况下这很好,因为所有事情都发生在一个电话中,但很好的呼唤。

    【讨论】:

      猜你喜欢
      • 2019-07-22
      • 1970-01-01
      • 2021-12-05
      • 2010-09-19
      • 1970-01-01
      • 2016-03-06
      • 1970-01-01
      • 2010-10-26
      相关资源
      最近更新 更多