在Oracle数据库中存储重复的时间段

时间:2015-02-24 14:57:45

标签: oracle time plsql monitoring cronexpression

我正在编写监控软件,其中大部分逻辑都在Oracle数据库和数据库中。 PL / SQL。

当我的监控被调用时,它应警告问题。例如,如果,它应警告问题  
1。星期五22:00至23:00,每分钟运行不到2次  
2。 1月31日22:00-23:00,每分钟运行不到5次  
3。从10:00到12:00,每天每分钟操作不到3次 如果我的监控在1月31日22:30召唤,我应该将我的操作号码与5进行比较。
4.如果操作少于5次,则每分钟从星期五22:00到星期一15:00


我正在考虑用数据库中的cron表达格式保存数据周期。在这种情况下,我必须将SYSDATE(监视函数的当前调用日期)与保存在数据库中的cron表达式进行比较。

我的问题:
1.如何判断SYSDATE是否属于cron表达式?
2。在这种情况下使用cron表达式是否正确?你能否建议任何其他节省时间的方法。

3 个答案:

答案 0 :(得分:4)

不要这样做

我完全使用SpaceTrucker:不要在SQL或PL / SQL中执行此操作,使用Java 8 date APIJodaTime在Java中执行此操作。

但如何做到

但即使你不应该这样做,也可能有一些很好的理由去做。所以这是如何:

您要检查的每个瞬间的表

首先,让我们在您要检查的时间间隔内为每秒或分钟创建一个表。间隔的粒度和长度取决于您要允许的cron表达式。通常一周一秒应该足够(大约100&#39,000行)。如果要检查整年,请使用分钟作为粒度(大约500&#39,000行)。数量或行都不适用于现代数据库。在我的笔记本上,根据查询立即返回。

CREATE TABLE week AS
SELECT 
  running_second,
  ts, 
  EXTRACT(SECOND FROM ts) as sec,
  EXTRACT(MINUTE FROM ts) as min,
  EXTRACT(HOUR FROM ts) as h,
  to_char(ts, 'Day') as dow
FROM (  
  SELECT 
    level as running_second,
    TO_TIMESTAMP_TZ('2015-09-05 00:00:00 0:00',
     'YYYY-MM-DD HH24:MI:SS TZH:TZM') + 
     NUMTODSINTERVAL(level-1, 'SECOND') AS ts
  FROM dual CONNECT BY level<=60*60*24*7
)
;

查询每个过滤器表达式

接下来,将每个cron表达式转换为查询。您可以使用PL / SQL将每个cron表达式转换为where子句,也可以使用泛型where子句。

你应该得到这样的东西:

SELECT
  *
FROM
  week
WHERE
  h  =5
AND min=0
AND sec=0;

或通用版本:

SELECT
  filter_expression.name, week.ts
FROM
  week, filter_expressions
WHERE
  (fiter_hour is null or h  = filter_hour) 
AND (filter_min is null or min = filer_min)
AND (filter_sec is null or sec = filter_sec);

(假设您的过滤器存储在表filter_expressions中,每个约束类型都有一列,每行都有一个约束参数,如果约束不适用,则为NULL

将结果存储在全局临时表cron_startpoints中。

检查违规行为

将表格cron_startpoints分组以检查违规行为。您可以计算,周五或午夜有多少场比赛,或者可以检查,这个号码是否合适。

答案 1 :(得分:1)

这取决于你想要多少灵活性。对于您提供此类结构的示例就足够了:

CREATE TABLE monitoring_periods (
  id INTEGER NOT NULL PRIMARY KEY,
  monit_month VARCHAR2(2),
  monit_day VARCHAR(2),
  monit_day_of_week VARCHAR(3),
  monit_time_from INTERVAL DAY TO SECOND,
  monit_time_to INTERVAL DAY TO SECOND,
  required_ops INTEGER
);

Here是存储句点和检查sysdate的一些示例。我会避免将cron表达式字面上存储为字符串,因为它需要在查询时解析它。但是,表达式越复杂(类型为5 4,15,22 * / 2 * 1-5&#39;),存储结构越复杂 - 您需要仔细考虑您的要求。

答案 2 :(得分:1)

我曾经有过编写艰难日期计算的任务,其中重复周期和时间为10g。其中包括&#34;本月第二周的星期二,每2个月在上午8点到下午2点之间#34;我们决定使用java存储过程(也因为它们已经用于其他目的)。

根据您的oracle版本,您可以选择joda-time版本,该版本可以在oracle数据库jvm中运行。另请注意,joda-time 1.6可以使用java 1.3编译(我们必须使用它)。

如果您正在寻找明确的cron表达式,那么您在使用oracle数据库jvm中的另一个Java库时也可能做得很好。例如here就是一个:

CronExpression expression = CronExpression.parser()
            .withSecondsField(true)
            .withOneBasedDayOfWeek(true)
            .allowBothDayFields(false)
            .parse("0 15 10 L * ?");
assert expression.matches(dateTime);

但是我觉得cron不适合你手边的任务。 Cron是一种指定何时运行作业的方法。但是你需要观察发生的事情。因此,对于您的要求只有不到2个操作,每分钟您可以在第1秒和第2秒或第1个第31秒进行操作并且两者都有效,但它们的cron表达式非常不同。

如果要保存时间段,您还可以查看存储为varchars的ISO 8601 recurinng intervals

P1Y2M10DT2H30M

在任何情况下,您都需要对要匹配的每一行应用计算。根据有多少行,您可能需要使用一些启发式方法来分析远离满足条件的结果。

在盒子外面思考一下:

你应该质疑你的架构。您列出的要求可以由状态机表示。您可以使用按时间顺序发生的事件来提供它们。如果状态机达到某种不需要的状态,您只需报告该状态即可。但是我怀疑这可以在纯pl / sql中轻松完成。