近日,一客户遇到一oracle job的broken状态无法改变的灵异事件。
一、现象描述
根据客户描述,其维护的oracle数据库内有两个Job作业被停止了,但是Job的BROKEN状态一直是yes状态,使用Toad客户端工具修改成no之后,重新登陆Toad客户端查看被修改的job作业BROKEN状态属性依然是yes状态。
二、问题分析
接到问题之后,远程上去,客户演示了一遍问题发生的过程。站在DBA的角度,我不信任Toad第三方工具,于是让客户登陆shell连接到数据库服务器端,使用sql命令EXEC DBMS_JOB.BROKEN(23,FALSE); commit;直接修改,由于使用的是sys用户并非job作业的宿主,提示ORA-23421错误。于是,切换至job作业宿主执行job的broken状态更改,命令执行很顺利但是使用如下sql语句再次查看job状态时,发现job的broken属性还是yes,揉揉眼定睛再看依旧是yes。
SELECT JOB,NEXT_DATE,NEXT_SEC,FAILURES,BROKEN FROM DBA_JOBS where JOB=23;
到这里,个人觉得很奇怪,数据库应该给异常提示才对,于是查看下数据库的告警日志,果然有重大发现:
通过数据库的告警日志发现执行EXEC DBMS_JOB.BROKEN(23,FALSE); commit;时,有ORA-12005告警提示,根据提示的信息猜测相关job作业的interval属性设置有问题。于是,查看job的interval配置信息,配置信息如下图:
根据job作业的interval设置trunc(sysdate,'MM')+14+1/24,询问客户设置的意图为每个月14号自动执行该job作业。但是,job作业的interval设置就有问题了,一旦过了当前月份的14号相当于job作业执行完了最后一次不循环执行,所以,11月16日interval时间变成11月14日,当手工再次执行EXEC DBMS_JOB.BROKEN(23,FALSE); commit;修改作业自动执行broken状态时提示ORA-12005。
三、问题处理
客户的目的,需要设置的job作业interval为Interval=>TRUNC(LAST_DAY(SYSDATE))+14+1/24,意思是当月14日执行完该job作业后,job的下次执行计划安排在下个月的14日,job作业的broken状态就不会自动变为yes且无法修改为no。
小插曲:客户在按提示修改job作业interval属性时,误将Interval=>TRUNC(LAST_DAY(SYSDATE))+14+1/24整体填进toad客户端interval属性框,提交修改时提示ORA-06550如下图,其实问题很简单,只需将日期运算公式TRUNC(LAST_DAY(SYSDATE))+14+1/24填进toad客户端的interval即可。其实,个人建议Toad应该在第一次修改job作业broken状态时提示错误ORA-12005,这样就能第一时间发现问题。
根据提示,客户最终成功完成了job作业的重置:
四、问题总结
客户端工具使用过程中相比服务器端有差距,不利于问题的第一时间发现;程序编制过程中,最好做测试,避免类似作业异常排查发现这种日期类逻辑错误问题;熟悉客户端的使用方法,避免类似ORA-06550低级错误。