如何安全地安排Oracle dbms_scheduler作业时区和DST

Jav*_*avo 8 timezone dbms-scheduler oracle11g dst job-scheduling

我正在尝试设置一个DBMS_SCHEDULER作业,以便在每年1月1日凌晨1点在Oracle 11g上运行.如何设置其属性以确保它不会在错误的时间执行,因为时区差异或夏令时.

我花了很多时间浏览Oracle文档,但我还没有达到确定性水平.

顺便说一句,以下是我发现并考虑与该主题相关的规则:

工作属性

start_date 此属性指定计划启动此作业的第一个日期.如果start_date和repeat_interval保留为null,则作业将在计划启动后立即运行.对于重复使用日历表达式指定重复间隔的作业,start_date用作参考日期.第一次安排作业运行是当前日期或之后的日历表达式的第一个匹配.调度程序无法保证作业将在准确的时间执行,因为系统可能会过载,因此资源不可用.

repeat_interval此属性指定作业重复的频率.您可以使用日历或PL/SQL表达式指定重复间隔.评估指定的表达式以确定下次运行作业的时间.如果未指定repeat_interval,则作业将仅在指定的开始日期运行一次.有关详细信息,请参阅"日历语法".

Calendaring语法中的规则

  • 日历语法不允许您指定时区.而是Scheduler从start_date参数中检索时区.如果作业必须遵循夏令时调整,则必须确保为start_date的时区指定区域名称.例如,在纽约将start_date时区指定为"US/Eastern"将确保自动应用夏令时调整.如果将start_date的时区设置为绝对偏移量(例如"-5:00"),则不会遵循夏令时调整,并且您的作业执行将在一年中的一个半小时内关闭.
  • 当start_date为NULL时,Scheduler将确定重复间隔的时区,如下所示:
  • 它将检查会话时区是否为区域名称.会话时区可以通过以下任一方式设置:发出ALTER SESSION语句,例如:SQL> ALTER SESSION SET time_zone ='Asia/Shanghai'; 设置ORA_SDTZ环境变量.
  • 如果会话时区是绝对偏移而不是区域名称,则调度程序将使用DEFAULT_TIMEZONE Scheduler属性的值.有关更多信息,请参阅SET_SCHEDULER_ATTRIBUTE过程.
  • 如果DEFAULT_TIMEZONE属性为NULL,则在启用作业或窗口时,调度程序将使用systimestamp的时区.

Jav*_*avo 1

我不确定这个答案是否真正通过了该网站上的答案规则,但在花了很多时间谷歌搜索后,我想出了以下解决方案:

start_date      => CAST(trunc(sysdate, 'YEAR')+2/24 AS TIMESTAMP) at time zone 'Europe/Berlin'
Run Code Online (Sandbox Code Playgroud)

我相信这是最接近最安全的解决方案,因为:

  • 它使用时间戳而不是日期 - 我相信它会强制作业在给定时区的给定时间真正执行,同时忽略 DMBS_SCHEDULER default_timezone。我还发现一些建议说直接使用时间戳也是不安全的,只有这个强制转换是安全的
  • 我手动选择了我需要的时区,希望它不会与本地设置发生冲突。尽管我不清楚它现在是否真的与 SESSIONTIMEZONE 或 DBTIMEZONE 无关,以及它是否影响正确的运行时间。
  • 我使用了一些技巧,即使要求工作应该在午夜之后开始,我也将其设置为凌晨 2 点,希望即使在时区和夏令时不好的情况下,它也会移动到 max +-2小时。

如果我能绝对清楚何时根据服务器的本地时间、SESSIONTIMEZONE、DBTIMEZONE、start_date 时区和 DBMS_SCHEDULER 时区实际执行作业,我会对解决方案感到更满意。

我对时区规范也不满意,因为它有 4 个与之相关的缩写 - LMT、CET、CEST、CEMT,其中 CEST 在我看来是完全错误的。我的目标是使用 CET 和夏令时(冬季!=夏季)。