【发布时间】:2016-12-05 17:53:14
【问题描述】:
我在一个实例中有大约 40 个不同的 sql server 作业。他们都有不同的时间表。有的每天跑一次,有的每两分钟跑一次,有的每五分钟跑一次。如果我需要停止 sql server 代理,我怎样才能找到没有作业运行的最佳时间,这样我就不会中断我的任何作业?
【问题讨论】:
标签: sql-server jobs agent
我在一个实例中有大约 40 个不同的 sql server 作业。他们都有不同的时间表。有的每天跑一次,有的每两分钟跑一次,有的每五分钟跑一次。如果我需要停止 sql server 代理,我怎样才能找到没有作业运行的最佳时间,这样我就不会中断我的任何作业?
【问题讨论】:
标签: sql-server jobs agent
我怎样才能找到没有作业运行的最佳时间,这样我就不会打断我的任何作业?
您基本上是想找到一个好的窗口来执行一些维护。 @MaxVernon 已经在博客上写了 here 并附有一个方便的脚本
/*
Shows gaps between agent jobs
-- http://www.sqlserver.science/tools/gaps-between-sql-server-agent-jobs/
-- requires SQL Server 2012+ since it uses the LAG aggregate.
Note: On SQL Server 2005, SQL Server 2008, and SQL Server 2008 R2, you could replace the LastEndDateTime column definition with:
LastEndDateTime = (SELECT TOP(1) s1a.EndDateTime FROM s1 s1a WHERE s1a.rn = s1.rn - 1)
*/
DECLARE @EarliestStartDate DATETIME;
DECLARE @LatestStopDate DATETIME;
SET @EarliestStartDate = DATEADD(DAY, -1, GETDATE());
SET @LatestStopDate = GETDATE();
;WITH s AS
(
SELECT StartDateTime = msdb.dbo.agent_datetime(sjh.run_date, sjh.run_time)
, MaxDuration = MAX(sjh.run_duration)
FROM msdb.dbo.sysjobs sj
INNER JOIN msdb.dbo.sysjobhistory sjh ON sj.job_id = sjh.job_id
WHERE sjh.step_id = 0
AND msdb.dbo.agent_datetime(sjh.run_date, sjh.run_time) >= @EarliestStartDate
AND msdb.dbo.agent_datetime(sjh.run_date, sjh.run_time) < = @LatestStopDate
GROUP BY msdb.dbo.agent_datetime(sjh.run_date, sjh.run_time)
UNION ALL
SELECT StartDate = DATEADD(SECOND, -1, @EarliestStartDate)
, MaxDuration = 1
UNION ALL
SELECT StartDate = @LatestStopDate
, MaxDuration = 1
)
, s1 AS
(
SELECT s.StartDateTime
, EndDateTime = DATEADD(SECOND, s.MaxDuration - ((s.MaxDuration / 100) * 100)
+ (((s.MaxDuration - ((s.MaxDuration / 10000) * 10000))
- (s.MaxDuration - ((s.MaxDuration / 100) * 100))) / 100) * 60
+ (((s.MaxDuration - ((s.MaxDuration / 1000000) * 1000000))
- (s.MaxDuration - ((s.MaxDuration / 10000) * 10000))) / 10000) * 3600, s.StartDateTime)
FROM s
)
, s2 AS
(
SELECT s1.StartDateTime
, s1.EndDateTime
, LastEndDateTime = LAG(s1.EndDateTime) OVER (ORDER BY s1.StartDateTime)
FROM s1
)
SELECT GapStart = CONVERT(DATETIME2(0), s2.LastEndDateTime)
, GapEnd = CONVERT(DATETIME2(0), s2.StartDateTime)
, GapLength = CONVERT(TIME(0), DATEADD(SECOND, DATEDIFF(SECOND, s2.LastEndDateTime, s2.StartDateTime), 0))
FROM s2
WHERE s2.StartDateTime > s2.LastEndDateTime
ORDER BY s2.StartDateTime;
【讨论】:
问题标题让我有点害怕 - 我以为您想在没有作业运行的任何时候以编程方式关闭 SQL Server 代理。我对这个问题的回答是“为什么?”没必要。
但是,如果您只是希望进行计划的重启或关闭,并且您没有像 Sentry One 的 SQL Sentry 事件管理器这样的第三方工具来进行可视化,我只会让 SQL Server Agent Job History 和作业活动监视器帮助在这里。作业活动监视器可以在状态列中显示当前正在运行的作业。您还可以查看上次执行和下次执行的日期和时间。
在 SSMS 的对象浏览器中,连接到您的实例,然后展开 SQL Server 代理,然后您将看到 Jobs 并在其下方看到“Job Activity Monitor” - 此视图应显示您需要的内容。
另外 - 不必担心在作业执行之前关闭。如果你这样做了,你要么让那个作业错过它的时间表,你可以让它在下一次运行时运行(取决于作业和它的目的),或者你可以手动右键单击并执行作业。
有关作业活动监视器的更多信息,请参阅产品文档中的Monitor Job Activity。
【讨论】:
我建议创建一个脚本来禁用您的作业。禁用的作业仍然存在,但不会按其计划自动启动。运行此脚本(基于 msdb 数据库中的过程 sp_update_job)以禁用作业,等待任何当前正在运行的作业完成执行,然后停止 SQL 代理。重新启用已禁用作业的类似脚本会很有用。您可能需要围绕已禁用且应保持禁用的作业进行规划。
可以完全编写完整的“SQL 代理关闭”过程,但我质疑这样做是否明智。一些研究表明,没有 100% 可靠的方式以编程方式判断给定作业是否正在运行,并且虽然存在未记录(其中“未记录”表示“您真的不应该使用此”)系统使用 SQL Server 本身来停止和启动服务的过程似乎是一个非常糟糕的主意。
【讨论】:
您可以查询 Dattatrey Sindol 在 MSSQLTips.com 文章Querying SQL Server Agent Job Information 中显示的系统表:
SELECT [sJOB].[job_id] AS [JobID] , [sJOB].[name] AS [JobName] , [sDBP].[name] AS [JobOwner] , [sCAT].[name] AS [JobCategory] , [sJOB].[description] AS [JobDescription] , CASE [sJOB].[enabled] WHEN 1 THEN 'Yes' WHEN 0 THEN 'No' END AS [IsEnabled] , [sJOB].[date_created] AS [JobCreatedOn] , [sJOB].[date_modified] AS [JobLastModifiedOn] , [sSVR].[name] AS [OriginatingServerName] , [sJSTP].[step_id] AS [JobStartStepNo] , [sJSTP].[step_name] AS [JobStartStepName] , CASE WHEN [sSCH].[schedule_uid] IS NULL THEN 'No' ELSE 'Yes' END AS [IsScheduled] , [sSCH].[schedule_uid] AS [JobScheduleID] , [sSCH].[name] AS [JobScheduleName] , CASE [sJOB].[delete_level] WHEN 0 THEN 'Never' WHEN 1 THEN 'On Success' WHEN 2 THEN 'On Failure' WHEN 3 THEN 'On Completion' END AS [JobDeletionCriterion] FROM [msdb].[dbo].[sysjobs] AS [sJOB] LEFT JOIN [msdb].[sys].[servers] AS [sSVR] ON [sJOB].[originating_server_id] = [sSVR].[server_id] LEFT JOIN [msdb].[dbo].[syscategories] AS [sCAT] ON [sJOB].[category_id] = [sCAT].[category_id] LEFT JOIN [msdb].[dbo].[sysjobsteps] AS [sJSTP] ON [sJOB].[job_id] = [sJSTP].[job_id] AND [sJOB].[start_step_id] = [sJSTP].[step_id] LEFT JOIN [msdb].[sys].[database_principals] AS [sDBP] ON [sJOB].[owner_sid] = [sDBP].[sid] LEFT JOIN [msdb].[dbo].[sysjobschedules] AS [sJOBSCH] ON [sJOB].[job_id] = [sJOBSCH].[job_id] LEFT JOIN [msdb].[dbo].[sysschedules] AS [sSCH] ON [sJOBSCH].[schedule_id] = [sSCH].[schedule_id] ORDER BY [JobName]
【讨论】: