如何在没有作业运行时自动停止SQL Server代理?

时间:2016-12-05 17:53:14

标签: sql-server jobs agent

我在一个实例中有大约40个不同的sql server作业。它们都有不同的时间表。有些人每天运行一次,每隔两分钟运行一次,每隔五分钟运行一次。如果我需要停止sql server agent,我怎样才能找到没有作业运行的最佳时间所以我不会打断我的任何工作?

4 个答案:

答案 0 :(得分:3)

问题标题让我有点害怕 - 我想你想在没有任何作业运行的情况下以编程方式关闭SQL Server代理。我对这个问题的回答是"为什么?"没有必要。

但是,如果您只是想要进行有计划的重启或关闭,并且您没有像Sentry One的SQL Sentry事件管理器这样的第三方工具来实现可视化,那么我只想让SQL Server代理作业历史记录和作业活动监视器帮助。 “作业活动”监视器可以在状态列中显示正在运行的作业。您还可以查看上次执行和下次执行日期和时间。

在SSMS中的对象浏览器中,连接到您的实例,然后展开SQL Server代理,然后您将看到作业,然后您将看到"作业活动监视器" - 此视图应显示您需要的内容。

另外 - 不要担心在工作执行前关闭。如果你这样做,你将要么让这个工作错过了它的计划,你可以让它在下一个时候运行(取决于工作及其目的),或者你可以手动右键单击并执行工作。

有关作业活动监视器的更多信息,请参阅产品文档中的Monitor Job Activity

答案 1 :(得分:3)

  

如何找到没有工作的最佳时间,这样我就不会打断我的任何工作?

您基本上想找到一个好的窗口来执行一些维护。 @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;

答案 2 :(得分:1)

我建议创建一个禁用作业的脚本。已禁用的作业仍然存在,但不会按其计划自动启动。运行此脚本(基于msdb数据库中的过程sp_update_job)以禁用作业,等待任何当前正在运行的作业完成执行,然后停止SQL代理。重新启用已禁用作业的类似脚本将非常有用。您可能需要计划应该保持禁用的作业。

完整的“SQL代理关闭”过程可以完全编写脚本,但我质疑这样做的智慧。一些研究表明,没有100%可靠的方式以编程方式告知给定的作业是否正在运行,而且有一个未记录的(其中“未记录的”意味着“你真的不应该使用它”)系统停止和启动服务的过程,从SQL Server本身这样做似乎是一个非常糟糕的主意。

答案 3 :(得分:1)

您可以在MSSQLTips.com文章Querying SQL Server Agent Job Information中查询Dattatrey Sindol所示的系统表:

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]