如果您曾经认为取消 oracle job很容易,那么让我向您展示让我今天头痛的事情。
我们正在测试一个使用自定义代码在数据库之间出队和传播AQ消息的应用程序。共有9个流程,所有流程都使用提交为作业DBMS_JOB
。他们应该一直运行,等待消息出队。有时,我需要杀死它们以便重新编译它们正在执行的对象。
这些步骤非常简单:删除/中断所有有问题的作业,终止正在运行的作业,使用新版本重新编译软件包,然后再次提交/取消中断作业。但这一次,事情进展不如我预期的顺利。我们来看一下。
首先,我删除所有当前正在运行的作业:
SYS@ORCL>select 'exec dbms_ijob.remove('||job||');' from dba_jobs_running; 'EXECDBMS_IJOB.REMOVE('||JOB||');' ---------------------------------------------------------------- exec dbms_ijob.remove(261); exec dbms_ijob.remove(264); exec dbms_ijob.remove(267); exec dbms_ijob.remove(262); exec dbms_ijob.remove(265); exec dbms_ijob.remove(268); exec dbms_ijob.remove(263); exec dbms_ijob.remove(266); exec dbms_ijob.remove(269); 9 rows selected. SYS@ORCL>exec dbms_ijob.remove(261); PL/sql procedure successfully completed. SYS@ORCL> exec dbms_ijob.remove(264); PL/sql procedure successfully completed. SYS@ORCL> exec dbms_ijob.remove(267); PL/sql procedure successfully completed. SYS@ORCL> exec dbms_ijob.remove(262); PL/sql procedure successfully completed. SYS@ORCL> exec dbms_ijob.remove(265); PL/sql procedure successfully completed. SYS@ORCL> exec dbms_ijob.remove(268); PL/sql procedure successfully completed. SYS@ORCL> exec dbms_ijob.remove(263); PL/sql procedure successfully completed. SYS@ORCL> exec dbms_ijob.remove(266); PL/sql procedure successfully completed. SYS@ORCL> exec dbms_ijob.remove(269); PL/sql procedure successfully completed.
下一步,我将终止正在运行的作业的会话:
SYS@ORCL>select 'alter system kill session '''||sid||','||serial#||''';' from v$session where sid in (select sid from dba_jobs_running); 'ALTERSYstemKILLSESSION'''||SID||','||SERIAL#||''';' -------------------------------------------------------------------------------- alter system kill session '120,73'; alter system kill session '122,111'; alter system kill session '123,788'; alter system kill session '136,20'; alter system kill session '137,28'; alter system kill session '138,143'; alter system kill session '142,132'; alter system kill session '144,129'; alter system kill session '159,68'; 9 rows selected. SYS@ORCL>alter system kill session '120,73'; System altered. SYS@ORCL> alter system kill session '122,111'; System altered. SYS@ORCL> alter system kill session '123,788'; System altered. SYS@ORCL> alter system kill session '136,20'; System altered. SYS@ORCL> alter system kill session '137,28'; System altered. SYS@ORCL> alter system kill session '138,143'; System altered. SYS@ORCL> alter system kill session '142,132'; System altered. SYS@ORCL> alter system kill session '144,129'; System altered. SYS@ORCL> alter system kill session '159,68'; System altered.
并且正在运行的工作不见了:
SYS@ORCL>select count(*) from dba_jobs_running; COUNT(*) ---------- 0
我认为这很好,但是几秒钟后工作又回来了!
SYS@ORCL> / COUNT(*) ---------- 9
我发现这种行为非常有趣,因此我在网上进行搜索,并找到了一个非常不错的博客,详细解释了DBMS_JOB
工作的行为。
这暗示了OS进程实际上可以使数据库进程保持活动状态。因此,我认为这听起来很合理-让我们杀死OS进程。
SYS@ORCL>!ps -ef | grep ora_j oracle 16234 1 0 12:58 ? 00:00:00 ora_j000_ORCL oracle 16236 1 9 12:58 ? 00:00:07 ora_j001_ORCL oracle 16238 1 9 12:58 ? 00:00:07 ora_j002_ORCL oracle 16240 1 0 12:58 ? 00:00:00 ora_j003_ORCL oracle 16242 1 0 12:58 ? 00:00:00 ora_j004_ORCL oracle 16244 1 8 12:58 ? 00:00:06 ora_j005_ORCL oracle 16246 1 9 12:58 ? 00:00:07 ora_j006_ORCL oracle 16248 1 0 12:58 ? 00:00:00 ora_j007_ORCL oracle 16250 1 9 12:58 ? 00:00:07 ora_j008_ORCL oracle 16280 15459 0 12:59 pts/0 00:00:00 /bin/bash -c ps -ef | grep ora_j oracle 16282 16280 0 12:59 pts/0 00:00:00 grep ora_j SYS@ORCL>!kill -9 16234 16236 16238 16240 16242 16244 16246 16248 16250 16252
做完了!
嗯,但不是真的-一段时间后,工作从死里复生。在不同的Oracle PID和不同的OS PID下。
SYS@ORCL>select count(*) from dba_jobs_running; COUNT(*) ---------- 9
现在,这让我感到非常困惑。我如何摆脱它们?
当然!我为什么以前没有想到这个?我将设置job_queue_processes
为0
。终止进程,它们将不会重生。
再次杀死所有进程。
糟糕,他们又回来了!请注意,作业已从DBA_JOBs
表中删除,正在运行的作业正在引用不存在的作业ID。他们如何重生?
SYS@ORCL>select j.what,j.job,r.sid from dba_jobs j,dba_jobs_running r where j.job in (select job from dba_jobs_running) and j.job=r.job order by j.what; no rows selected
我决定扩展我的工作知识,并阅读了James Koopmann的整个博客。然后我看到了光!在文章下的评论中提到的用户JB(感谢JB,我也学到了很难的方法),COMMIT
在操作作业后必须运行该用户。
因此,在完成上述所有操作之后,我只输入了。。。
SYS@ORCL> commit; Commit complete.
。。。然后又杀死了工作,宾果!那些讨厌的工作终于消失了。
我在过去使用DBMS_JOB
过相同的过程,但从未遇到过此问题,但是我意识到我总是切换到SYS
用户以终止会话,因此重新连接后会自动提交该用户。
值得一提的是,重新生成的作业没有执行应做的工作,这意味着它们没有使消息出队。我正在使用的数据库版本是10.2.0.4,对于DBMS_JOB
/ IJOB
,REMOVE
和broKEN
过程均适用,并且可能也适用于此程序包的其他过程。毕竟,事情就像提交一样简单,不是吗?