代码之家  ›  专栏  ›  技术社区  ›  Joseph Bui

如何让DBA暂停并恢复一个正在更新大表中每一行的存储过程?

  •  4
  • Joseph Bui  · 技术社区  · 15 年前

    我有一个大约有一百万行的表,我需要用冗长的计算结果更新表中的每一行(计算得到的每一行的结果可能不同)。因为这很耗时,DBA必须能够控制执行。这个特定的计算需要每年运行一次(它做一个年终总结)。我想使用dbms_scheduler.create_作业创建一个作业,该作业将从表中获取100行,更新它们,然后停止;该作业的下一次执行将在上一次执行停止的地方进行。

    我的第一个想法是在存储过程的末尾包含此代码:

    -- update 100 rows, storing the primary key of the last
    -- updated row in last_id
    -- make a new job that will run in about a minute and will
    -- start from the primary key value just after last_id
    dbms_scheduler.create_job
    ( job_name=>'yearly_summary'
    , job_type=>'STORED_PROCEDURE'
    , job_action=>'yearly_summary_proc(' || last_id || ')'
    , start_date=>CURRENT_TIMESTAMP + 1/24/60
    , enabled=>TRUE
    );
    

    但当存储过程运行时,我会得到这个错误:

    ORA-27486: insufficient privileges
    ORA-06512: at "SYS.DBMS_ISCHED", line 99
    ORA-06512: at "SYS.DBMS_SCHEDULER", line 262
    ORA-06512: at "JBUI.YEARLY_SUMMARY_PROC", line 37
    ORA-06512: at line 1
    

    欢迎提供其他方法的建议。我宁愿使用DBMS_调度程序,也不愿意创建任何表;这就是我将最后一个_i d传递给存储过程的原因。

    3 回复  |  直到 15 年前
        1
  •  7
  •   Justin Cave    15 年前

    我倾向于谨慎使用像这样的工作来控制执行。可能是连续作业之间的延迟太短,DBA无法确定要终止/暂停哪些作业,或者延迟的时间足够长,以至于连续作业之间的延迟会占用大量的运行时间。

    在不创建任何新对象的情况下,可以使用 DBMS_ALERT 允许DBA发送暂停作业的警报的包。您的代码可以调用 DBMS_ALERT.WAITONE 方法每隔100行检查DBA是否已发出特定警报(即 PAUSE_YEAREND_JOB 警报)如果没有收到警报,代码可能会继续。如果收到警报,您可以暂停代码,直到另一个警报(即 RESUME_YEAREND_JOB )收到或固定的时间段,或基于DBA发送的消息 暂停工作 警报(即消息可以是暂停的秒数或暂停到的日期等)

    当然,您也可以通过创建一个新表来做同样的事情,让DBA向表中写入一行以暂停作业,并每隔N行从表中读取一行。

        2
  •  2
  •   Jamie Love    15 年前

    另一种探索方法是DBMS调度器对执行窗口和资源计划的支持工具。

    http://www.oracle-base.com/articles/10g/Scheduler10g.php

    还有:

    http://download-west.oracle.com/docs/cd/B19306_01/server.102/b14231/schedover.htm#sthref3501

    使用Windows和资源计划,DBA可以简单地配置系统来执行您的过程,以遵守特定的规则-包括作业窗口,并且只使用特定数量的资源(即CPU使用率)执行。

    这样,该过程可以一年运行一次,并且可以控制CPU的使用。

    但这可能无法提供DBA想要的手动控制。

    另一个想法是编写处理所有记录的过程,但每隔1000左右提交一次。dbms job.cancel()命令可以被DBA用来取消要停止的作业,然后他们可以在准备好执行时(通过重新安排或重新运行)继续执行。诀窍是,该过程需要能够跟踪处理的行,例如使用“处理日期”列,或单独的表,列出主键和处理日期。

        3
  •  2
  •   WW.    15 年前

    除了回答关于 DBMS_ALERT ,您的DBA会很高兴看到您的存储过程在哪里。你应该使用 DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS Oracle中的功能。