终止正在运行的ORACLE作业

如果您曾经认为取消 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_processes0。终止进程,它们将不会重生。

SYS@ORCL>alter system set job_queue_processes=0;

System altered.

再次杀死所有进程。

SYS@ORCL>select count(*) from dba_jobs_running;

  COUNT(*)
----------
         0

SYS@ORCL>alter system set job_queue_processes=10;

System altered.

SYS@ORCL>select count(*) from dba_jobs_running;

  COUNT(*)
----------
         9

糟糕,他们又回来了!请注意,作业已从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_JOBIJOBREMOVEBROKEN过程均适用,并且可能也适用于此程序包的其他过程。毕竟,事情就像提交一样简单,不是吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值