记一次Oracle定时器调用存储过程的坑

本文详细记录了一次在预发布环境中,Oracle定时器未按预期执行存储过程的问题排查过程。从检查定时器状态、job_queue_processes参数到发现可能的Oracle 497天bug,最终发现问题是由于时区设置导致的。解决方案是重新配置定时器,确保其启动时间在正确的时区下。此案例强调了排查问题时对细节的关注和理解Oracle时区问题的重要性。
摘要由CSDN通过智能技术生成

背景

Oracle用scheduler写了一个定时器调用存储过程,每个月创建一次表。结果到定时器的执行时间了表却没有创建(预发布环境)。
本地环境正常,模拟环境正常,开发环境正常,测试环境正常
预发布环境异常没创建表
(此时心中:万马奔腾,不得不提一句,docker真香)

排查问题

刚发现这个问题的时候,一脸懵逼。特么本地环境,模拟环境,开发环境,测试环境都ok了,咋个预发布环境就出问题了??
在这里插入图片描述
带着一脸懵逼,还是默默打开了oracle,查看了下定时器

select job_name,start_date,next_run_date,repeat_interval from user_scheduler_jobs;

一打开(由于预发布环境没有权限动,现在查不了异常环境的图。下图是正常情况的,这里展示一下字段。异常信息由下面写出。):

查询后第一映入眼帘的是,我设置定时器每个月28号 09:15:05执行一次。咋到点了还没有表创建,NEXT_RUN_DATE字段下一次执行时间也没有更新

异常信息:

JOB_NAME:CREATE_TABLE_BY_MONTH

START_DATE:2020-09-27 18:13:05.046910 PST8PDT

NEXT_RUN_DATE:2020-09-28 09:15:05.000000 PST8PDT

REPEAT_INTERVAL:FREQ=MONTHLY; INTERVAL=1; BYMONTHDAY=28; BYHOUR=9; BYMINUTE=15
在这里插入图片描述

之后一顿百度操作猛如虎,查看各路大佬是否遇到这类问题

在这里插入图片描述
总结可能导致的原因如下:

  • oracle定时器job长时间执行无法结束。意思就是执行的时候,出于某种原因,数据库崩了之类的。job卡死。
  • 查询job_queue_processes参数
  • 系统uptime超过497天100%bug

尝试定位问题方式一:oracle定时器job长时间执行无法结束

参考学习博文:oracle定时器job长时间执行无法结束
之后一顿操作:

-- 描述正在运行的Job的相关信息
select * from dba_scheduler_running_jobs;

-- 描述已经完成的Job是否成功,记录相关日志的视图,这里记录着所有已经执行完毕的日程
select * from  user_scheduler_job_run_details;

select * from user_scheduler_job_log ;

-- 描述当前数据库所有已知的日程。
select * from  dba_scheduler_schedules;

-- 描述当前数据库已经定义完毕的程序
select * from  dba_scheduler_programs;

-- 描述当前数据库已经定义完毕的作业
select * from  dba_scheduler_jobs;

查询正在运行的Job的相关信息:发现并没有正在运行的
在这里插入图片描述
查询已经完成的Job是否成功,发现全是成功的
在这里插入图片描述

这时候,我:

在这里插入图片描述

说明并不是这个原因。下来继续尝试另外的方式定位。

尝试定位问题方式二:查询job_queue_processes参数

网上说是job_queue_processes这个参数的问题,如果为0就会失败。查询了一下,为1000.说明也不是这个问题

select value from v$parameter where name like '%job_queue_processes%';

alter system set job_queue_processes=1000;

在这里插入图片描述

尝试定位问题方式三:uptime 100% but only after 497 days.

参考学习博文:Oracle 定时器失效——解决

简述就是 Oracle的一个bug,uptime的时间只要超过497天就会定时器失效。

之后马上查了一下uptime。发现已经 440 days 了,欸。觉得还有可能是这个问题。超过497天 100%出问题,接近497天概率出问题。
在这里插入图片描述
但当我准备根据博文一系列操作的时候,发现:

啥?要重启主机??预发布环境还有客户在用呢??
在这里插入图片描述
于是继续搁置。尝试另外的方式。

此时一上午已经过去。。。。

换个思路,重头开始看(解决)

START_DATE:2020-09-27 18:13:05.046910 PST8PDT

突然再看一下定时器信息,咋个定时器开始时间:START_DATE还是前一天27号的时间???难道不应该是我执行定时器的时间吗??(定时器设置是开启即马上执行存储过程一次)

在这里插入图片描述
之后。。不停网上搜解决方式。。。

30 min later…
45 min later…
60 min later…

预发布环境的时间查完了,就是不知道这个START_DATE咋个出来的。
在这里插入图片描述

最后结论只有Oracle内部自己实现的START_DATE。(有无大佬可以指教一波,谢谢。网上搜半天都没找到讲解。)

在这里插入图片描述
之后找同事过来帮忙。。再一次看了下测试环境和预发布环境的user_scheduler_jobs信息。

同事: prc是啥?测试环境prc结尾,预发布环境PST8PDT结尾。

我:prc不知道,PST8PDT是个时区,美国加拿大那边的时区(之前注意到这的不同之处专门网上查了下,不过没在意这点!!!)

同事: 会不会就是这个时区问题

我(心里一惊):
START_DATE:2020-09-27 18:13:05.046910 PST8PDT

NEXT_RUN_DATE:2020-09-28 09:15:05.000000 PST8PDT

下图是正常环境的图,这里只做展示字段。

在这里插入图片描述
算了算,我们在东8区,PST8PDT是西8区,反正就是我们快了15个小时,意思就是我当时执行时间 09-27 18:13:05. + 15小时 = 09-28 9:13:05 , 鬼鬼,就是我排查问题的时间!!!问题就是这!!

此时:已下班1小时。。。

在这里插入图片描述

之后重新删了drop定时器,开启一个设置每次执行时间在START_DATE后面几分钟。测试成功,表成功创建。。。

整理一下时区查询的sql

-- 查询系统时间,数据库时间等等
select sysdate,systimestamp,current_date,current_timestamp,dbtimezone,sessiontimezone from dual;

-- 查询时区
SELECT * FROM V$TIMEZONE_NAMES;

SELECT * FROM V$TIMEZONE_NAMES WHERE TZNAME='PST8PDT';

SELECT * FROM V$TIMEZONE_NAMES WHERE TZNAME='PRC';

-- 比标准时间差多少小时
select tz_offset('PST8PDT') from dual;

-- 时区转换
select to_char(new_time(to_date('13-12-2013 17:03','dd-mm-yyyy hh24:mi'),'PST','EST'),'YYYY-MM-DD HH24:MI') from dual;



查询时区:

在这里插入图片描述
查询相差时间:

在这里插入图片描述
得到正在运行job的 session id

如果job 使用DBMS_JOB package创建,请使用如下语句:

set feedback off
alter session set nls_date_format=‘DD-MON-YYYY HH24:MI:SS’;
set feedback on

select jr.job, s.username, s.sid, s.serial#, p.spid, s.lockwait, s.logon_time
from dba_jobs_running jr, v s e s s i o n s , v session s, v sessions,vprocess p
where jr.sid = s.sid
and s.paddr = p.addr
order by jr.job;

如果job 使用DBMS_SCHEDULER 创建,请使用如下语句:

set feedback off
alter session set nls_date_format=‘DD-MON-YYYY HH24:MI:SS’;
set feedback on

select rj.job_name, s.username, s.sid, s.serial#, p.spid, s.lockwait, s.logon_time
from dba_scheduler_running_jobs rj, v s e s s i o n s , v session s, v sessions,vprocess p
where rj.session_id = s.sid
and s.paddr = p.addr
order by rj.job_name;

总结

  • 不要放过任何一个不起眼的异常点,有时候的你以为没有问题就是一个思维盲区,陷进去就出不来了
  • Oracle时区问题真坑(吐槽)
  • 至此Oracle定时器START_DATE都不知道咋个计算的,需深入了解Oracle底层
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值