SQL 代理:设置最大执行时间

发布于 2024-10-21 16:38:09 字数 2282 浏览 1 评论 0原文

下午。我在 MS 2K8 BI 服务器上运行多个 SQL 代理作业,其中一些每天运行一次,其他每小时运行一次,每两分钟运行一次(另一个进程的心跳监视器)。还有一个应用程序可以全天候每隔几分钟导入一次数据。有时,更新和报告的某些组合会发生冲突,其中一个或另一个会挂起半小时或更长时间,而不是通常的 60 秒。

虽然我需要找到这些竞争条件的根源,但与此同时,我想将某些作业设置为在五分钟后自动终止。我可以在 SSIS 或 Windows 计划任务中执行此操作,但在 SQL 代理中看不到任何方法。这可能吗,还是我需要将任务包装在 SSIS 包中才能获得这种控制?


仅供参考,这是我最终使用的 SQL 代理作业:

DECLARE @Cancelled BIT
EXEC dbo.CancelJob @JobName = 'ETL - Daily', @Cancelled = @Cancelled OUT

IF @Cancelled = 1
    BEGIN
    DECLARE @Success INT
    EXEC @Success = msdb..sp_send_dbmail
        @profile_name = 'Reporting',
        @recipients = '[email protected]',
        @subject = 'Cancelled Daily ETL'
    IF @Success <> 0 RAISERROR('An error occurred while attempting to send an e-mail.', 16, @Success)
    END

...这是 CancelJob 背后的代码:

CREATE PROCEDURE dbo.CancelJob(@JobName VARCHAR(100), @OwnerName VARCHAR(100) = NULL, @Cancelled BIT OUT)
AS BEGIN
    IF @OwnerName IS NULL SET @OwnerName = SUSER_NAME()
    SET @Cancelled = 0

    CREATE TABLE #JobInfo
        ( 
        Job_ID  UNIQUEIDENTIFIER,
        Last_Run_Date   INT,
        Last_Run_Time   INT,
        Next_Run_Date   INT,
        Next_Run_Time   INT,
        Next_Run_Schedule_ID    INT,
        Requested_To_Run    INT,
        Request_Source  INT,
        Request_Source_ID   VARCHAR(100),
        Running INT,  -- This is the only field we want (sigh)
        Current_Step    INT,
        Current_Retry_Attempt   INT,
        State   INT
        )
    INSERT INTO #JobInfo
        EXEC xp_sqlagent_enum_jobs 1, @OwnerName

    DECLARE @Running INT = (SELECT Running FROM #JobInfo AS JI INNER JOIN msdb..sysjobs_view AS J ON JI.Job_ID = J.job_id WHERE J.name = @JobName)
    IF @Running = 1
        BEGIN
        BEGIN TRY
            EXEC msdb..sp_stop_job @job_name = @JobName
            SET @Cancelled = 1
        END TRY
        BEGIN CATCH
            -- If an error occurs, it is *probably* because the job finished before we could cancel it, which is fine
        END CATCH
        END
END
GO

xp_sqlagent_enum_jobs 是避免无法捕获的错误的技巧。

Afternoon. I have several SQL Agent jobs running on an MS 2K8 BI server, some of them on a daily basis, others hourly, and one every two minutes (a heartbeat monitor for another process). There is also an app which imports data every few minutes, around the clock. Occasionally some combination of updates and reports collide and one or another hangs for a half hour or more, instead of the usual 60 seconds.

While I need to get to the root of these race conditions, in the meantime I'd like to set certain jobs to automatically die after, say, five minutes. I can do this in SSIS or a Windows scheduled task, but I don't see any way to do so in SQL Agent. Is this possible, or do I need to wrap the task in an SSIS package to get this kind of control?


FYI, here's the SQL Agent job I ended up using:

DECLARE @Cancelled BIT
EXEC dbo.CancelJob @JobName = 'ETL - Daily', @Cancelled = @Cancelled OUT

IF @Cancelled = 1
    BEGIN
    DECLARE @Success INT
    EXEC @Success = msdb..sp_send_dbmail
        @profile_name = 'Reporting',
        @recipients = '[email protected]',
        @subject = 'Cancelled Daily ETL'
    IF @Success <> 0 RAISERROR('An error occurred while attempting to send an e-mail.', 16, @Success)
    END

...and here's the code behind CancelJob:

CREATE PROCEDURE dbo.CancelJob(@JobName VARCHAR(100), @OwnerName VARCHAR(100) = NULL, @Cancelled BIT OUT)
AS BEGIN
    IF @OwnerName IS NULL SET @OwnerName = SUSER_NAME()
    SET @Cancelled = 0

    CREATE TABLE #JobInfo
        ( 
        Job_ID  UNIQUEIDENTIFIER,
        Last_Run_Date   INT,
        Last_Run_Time   INT,
        Next_Run_Date   INT,
        Next_Run_Time   INT,
        Next_Run_Schedule_ID    INT,
        Requested_To_Run    INT,
        Request_Source  INT,
        Request_Source_ID   VARCHAR(100),
        Running INT,  -- This is the only field we want (sigh)
        Current_Step    INT,
        Current_Retry_Attempt   INT,
        State   INT
        )
    INSERT INTO #JobInfo
        EXEC xp_sqlagent_enum_jobs 1, @OwnerName

    DECLARE @Running INT = (SELECT Running FROM #JobInfo AS JI INNER JOIN msdb..sysjobs_view AS J ON JI.Job_ID = J.job_id WHERE J.name = @JobName)
    IF @Running = 1
        BEGIN
        BEGIN TRY
            EXEC msdb..sp_stop_job @job_name = @JobName
            SET @Cancelled = 1
        END TRY
        BEGIN CATCH
            -- If an error occurs, it is *probably* because the job finished before we could cancel it, which is fine
        END CATCH
        END
END
GO

xp_sqlagent_enum_jobs was the trick to avoid the uncatchable error.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

趁年轻赶紧闹 2024-10-28 16:38:09

我从来不需要经常这样做,所以可能有更好的长期解决方案,但我创建了第二个工作来停止第一个工作,在我必须执行此任务的极少数情况下。我只是使用 sp_stopjob 过程来执行此操作。

I have never had to do this frequently, so there may be better long-term solutions, but I have created a second job to stop the first on the rare occasions that I had to perform this task. I just used the sp_stopjob procedure to do this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文