65.9K
CodeProject 正在变化。 阅读更多。
Home

简单动态调度器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.86/5 (18投票s)

2016年5月2日

CPOL

7分钟阅读

viewsIcon

48313

downloadIcon

2824

简单、开源、完全可定制、轻量级的 SQL Server 调度程序

引言

Simple Dynamic Scheduler 是一种替代性的调度实用程序,它使用 SQL Server 来存储所有配置和逻辑。Simple Dynamic Scheduler 的主要特点是:

  • 简单 - 易于管理(阅读完本页后)
  • 动态 - 非静态
  • 纯 T-SQL - 不言而喻
  • 开源 - 可适应的代码,满足您的业务需求
  • 轻量级 - 提供决策机制(运行或保持)而无需实际执行任何操作

如今有许多现成的调度程序可供使用,例如 Windows 任务、SQL Server 作业调度程序、第三方工具等。但是,请考虑以下情况

  • 您无法使用任何现成的调度程序。
  • 您可以使用现成的调度程序,但添加/修改/删除/禁用/启用调度程序需要时间和涉及大量内部流程(等待 OPS 或 DBA)。
  • 创建数百或数千个调度任务/作业是不切实际的。
  • 您的调度程序应根据特定的业务规则而变化。

如果以上任何一种情况听起来很熟悉,那么 Simple Dynamic Scheduler 可能是您的理想解决方案。

背景

Simple Dynamic Scheduler 是以 SQL Server 调度作业为参考构建的。它允许您定义:

  • 调度程序的名称
  • 计划类型(一次性或定期)
  • 计划频率(每日、每周、每月)
  • 重复(调度程序每 X 天、周、月重复一次)
  • 运行的星期几(适用于每周计划)
  • 每月运行的特定日期或工作日(适用于每月计划)
  • 每日发生次数(每天一次或多次)
  • 调度程序的保留期(开始日期和结束日期)
  • 活跃/有效日期(运行计划的日期)
  • 调度程序是否活跃(启用或禁用)

所有调度程序的所有配置参数都存储在配置表中。配置表中未存储的唯一信息是使用特定调度程序的进程的最后执行时间,因为多个进程可以使用同一个调度程序。因此,您需要为您的进程单独维护此信息。

Simple Dynamic Scheduler 的代码非常直接,它由以下几部分组成:

  • 包含计划配置的表 (t_SimpleDynamicScheduler)
  • 确定特定调度程序是否应运行的标量函数 (f_SimpleDynamicScheduler_CheckRun)
  • 用于模拟计划运行序列的表值函数 (f_SimpleDynamicScheduler_Simulate)

创建数据库对象时,请记住遵循此确切的执行顺序。

调度程序类型

使用 Simple Dynamic Scheduler 可以创建以下类型的调度程序:

  • 一次性
  • 定期
    • 每日
    • 每周
    • 每月
      • 在特定日期
      • 在特定工作日

此外,所有定期调度程序可能都有日内计划(每天运行一次以上)。下图显示了 t_SimpleDynamicScheduler 表中需要根据我们要创建的调度程序类型进行填充的列。

绿色字段为必填,黄色为可选,红色为忽略。我们将通过示例展示如何创建各种类型的调度程序。

创建调度程序

如前所述,可以使用 Simple Dynamic Scheduler 定义 5 种不同类型的调度程序。我们将通过示例,使用虚构的场景来解释如何创建每种类型的调度程序。在场景中,我们将划线标出重要的词语,并用下标数字标记。之后,我们将使用这些下标数字来解释场景中的信息应如何转换为配置表字段。

一次性调度程序

假设我们想创建一个一次性调度程序,它将在2016 年 4 月 5 日下午10:30触发。应初始化以下字段:

  • Name = 我的一次性调度程序 (可以是任何名称)
  • ¹Type = O
  • ³TimeStart = 22:30:00
  • ²StartDate = 2016-04-05
  • Enabled = True

定期、每日调度程序

如果我们想创建一个定期每日调度程序,它将每三天每天一次上午 9:00触发,从 2016 年 4 月 20 日开始,到 2016 年 5 月 31 日结束,我们将初始化以下字段:

  • Name = 我的每日定期调度程序 (可以是任何名称)
  • ¹Type = R
  • ²Frequency = D
  • ³RecurseEvery = 3
  • DailyFrequency = O
  • TimeStart = 9:00:00
  • StartDate = 2016-04-20
  • EndDate = 2016-05-31 (包含在内)
  • Enabled = True

定期、每周调度程序

让我们设想创建一个定期每周调度程序,它将在每两周周一、周四和周五每天一次触发,在下午 2:30从 2016 年 3 月 15 日开始。

  • Name = 我的每周定期调度程序 (可以是任何名称)
  • ¹Type = R
  • ²Frequency = W
  • ³RecurseEvery = 2
  • DaysOfWeek = Mo-Th-Fr
  • DailyFrequency = O
  • TimeStart = 14:30:00
  • StartDate = 2016-03-15
  • Enabled = True

定期、每月特定日期调度程序

在下一个示例中,我们将创建一个定期每月调度程序,它将在每三个月12 日触发,每天一次上午 11:00从 2016 年 2 月 10 日₇ 仅在工作日触发。

  • Name = 我的每月特定日期定期调度程序 (可以是任何名称)
  • ¹Type = R
  • ²Frequency = M
  • RecurseEvery = 3
  • ³MonthlyOccurrence = D
  • ³ExactDateOfMonth = 12
  • DailyFrequency = O
  • TimeStart = 11:00:00
  • StartDate = 2016-02-10
  • ValidDays = Mo-Tu-We-Th-Fr
  • Enabled = True

定期、每月特定工作日调度程序

与上一个调度程序类似,如果我们想创建一个定期每月调度程序,它将在每个月的第二个星期日触发,每天一次晚上 11:45从 2016 年 1 月 1 日到 2016 年 12 月 31 日

  • Name = 我的每月特定工作日定期调度程序 (可以是任何名称)
  • ¹Type = R
  • ²Frequency = M
  • RecurseEvery = 1
  • MonthlyOccurrence = W
  • ExactWeekdayOfMonth = Su
  • ³ExactWeekdayOfMonthEvery = 2
  • DailyFrequency = O
  • TimeStart = 23:45:00
  • StartDate = 2016-01-01
  • EndDate = 2016-12-31 (包含在内)
  • Enabled = True

日内调度程序(适用于所有定期调度程序)

日内调度程序用于在一天内多次运行调度的情况。例如,假设我们希望调度程序每天运行多次从上午 9:00开始,到下午 5:00结束,每小时运行一次。应初始化以下字段:

  • ¹DailyFrequency = E
  • ²TimeStart = 9:00:00
  • OccursEveryValue = 2
  • OccursEveryTimeUnit = H
  • ³TimeEnd = 17:00:00

  • ¹DailyFrequency = E
  • ²TimeStart = 9:00:00
  • OccursEveryValue = 120
  • OccursEveryTimeUnit = M
  • ³TimeEnd = 17:00:00

检查计划是否应运行

要确定特定计划是否应运行,我们将使用一个名为 [dbo].[f_SimpleDynamicScheduler_CheckRun] 的标量函数。

SELECT [dbo].[f_SimpleDynamicScheduler_CheckRun] (
     <@pScheduleId, int,>
    ,<@pLastRun, datetime,>
    ,<@pCurrentDate, datetime,>)

此函数的参数是:

  • <a>@pScheduleId</a> - 计划的 ID(配置表中的 ID 列)
  • <a>@pLastRun</a> - 使用此调度程序的进程/作业/活动的最后一次运行时间
  • @pCurrentDate - 当前日期和时间(通常是 getdate(),作为参数保留以供测试和模拟)

函数返回以下值:

  • RUN - 进程应运行
  • HOLD - 进程不应运行
  • 其他任何值 - 函数出现错误。返回值是错误的实际文本。

根据返回的结果,您应该在代码中实现逻辑来:

  1. 在必要时运行必要的代码
  2. 如果进程成功完成,则更新进程的 LastRun
  3. 向用户显示错误(如果有)

计划模拟器

为了进行测试和模拟,我们提供了一个名为 [dbo].[f_SimpleDynamicScheduler_Simulate] 的函数。它使您能够通过在定义的时期内模拟其使用来测试计划执行周期。

让我们以以下计划为例:

  • ID = 3
  • Type = R
  • Frequency = D
  • RecurseEvery = 1
  • DailyFrequency = E
  • TimeStart = 9:00:00
  • OccursEveryValue = 120
  • OccursEveryTimeUnit = M
  • TimeEnd = 16:30:00
  • StartDate = 2016-04-25
  • EndDate = 2016-05-13
  • Enabled = True

为了模拟此计划,我们将运行以下代码片段:

SELECT *
FROM [dbo].[f_SimpleDynamicScheduler_Simulate] (3, '20160405', '20160520', 'M', 10, null)

此函数参数的含义是:对于计划 3,从 2016 年 4 月 5 日2016 年 5 月 20 日,以10 分钟的增量模拟执行。之前的 LastRun 未知 (NULL)。

下图显示了模拟器提供的结果。

摘要

此时,您应该熟悉如何创建、初始化和使用 Simple Dynamic Scheduler。如果仍有不清楚的地方或我遗漏了什么,请随时提问和评论,我将确保对这些方面进行更好的解释。

享受使用 Simple Dynamic Scheduler 的乐趣!

历史

  • 2016 年 4 月 - 初始版本
  • 2016 年 5 月 - 添加了 ValidDays 参数,该参数控制计划的“有效”日期。例如,通过此新功能,我们可以通过仅将周一至周五设置为有效日期来控制计划是否可以在周末运行。
© . All rights reserved.