通过SQL Agent重新触发SSIS程序包

时间:2018-10-17 18:38:34

标签: ssis

我有一个SSIS ETL,因为它一直期待着新文件的到来,所以我需要它在完成后自动重新启动。但是,我不希望实例连续循环运行。

我的想法是在最后一个程序包完成之前使用Execute SQL Agent任务,但我已经对此进行了测试,但我收到一条错误消息,指出无法由拥有活动作业的同一用户启动SQL Agent作业运行。

我正在寻找有关重新触发SQL代理作业的最佳方法的一些建议。我当时在考虑创建一个单独的工作,然后执行该工作以开始所需的工作-我想尽管这样做必须有更好的方法。

欢迎任何建议或指点。

谢谢

2 个答案:

答案 0 :(得分:2)

由于您不希望SSIS包连续不断地运行,因此可以安排SQL Agent作业每10秒运行一次。那是我最常能安排工作的时间。如果作业的上一次运行仍在10秒后进行,则它将不会启动该程序包的另一个实例。完成后,它将在10秒后再次启动。

答案 1 :(得分:0)

我在Polling in SQL Agent上整理了一条帖子,该查询每5秒检查一次文件,最长不超过60秒(所有时间均可配置)

SET NOCOUNT ON;
-- http://www.patrickkeisler.com/2012/11/how-to-use-xpdirtree-to-list-all-files.html
DECLARE
    -- Don't do stupid things like adding spaces into folder names
    @sourceFolder varchar(260) = 'C:\ssisdata\Input'
    -- Have to use SQL matching rules, not DOS/SSIS
,   @fileMask sysname = 'SourceData%.txt'
    -- how long to wait between polling
,   @SleepInSeconds int = 5
    -- Don't exceed 24 hours aka 86400 seconds
,   @MaxTimerDurationInSeconds int = (3600 * 0) + (60 * 1) + 0
    -- parameter for xp_dirtree 0 => top folder only; 1 => subfolders
,   @depth int = 1
    -- parameter for xp_dirtree 0 => directory only; 1 => directory and files
,   @collectFile int = 1
,   @RC bigint = 0;

-- Create a table variable to capture the results of our directory command
DECLARE
    @DirectoryTree table
(
    id int IDENTITY(1, 1)
,   subdirectory nvarchar(512)
,   depth int
,   isFile bit
);

-- Use our sleep in seconds time to generate a delay time string
DECLARE
    @delayTime char(10) = CONVERT(char(10), TIMEFROMPARTS(@SleepInSeconds/60 /60, @SleepInSeconds/60, @SleepInSeconds%60, 0, 0), 108)
,   @stopDateTime datetime2(0) = DATEADD(SECOND, @MaxTimerDurationInSeconds, CURRENT_TIMESTAMP);

-- Force creation of the folder
EXECUTE dbo.xp_create_subdir @sourceFolder;

-- Load the results of our directory
INSERT INTO
    @DirectoryTree
(
    subdirectory
,   depth
,   isFile
)
EXECUTE dbo.xp_dirtree
    @sourceFolder
,   @depth
,   @collectFile;

-- Prime the pump
SELECT
    @RC = COUNT_BIG(1)
FROM
    @DirectoryTree AS DT
WHERE
    DT.isFile = 1
    AND DT.subdirectory LIKE @fileMask;

WHILE @rc = 0 AND @stopDateTime > CURRENT_TIMESTAMP
BEGIN

    -- Load the results of our directory
    INSERT INTO
        @DirectoryTree
    (
        subdirectory
    ,   depth
    ,   isFile
    )
    EXECUTE dbo.xp_dirtree
        @sourceFolder
    ,   @depth
    ,   @collectFile;

    -- Test for file existence
    SELECT
        @RC = COUNT_BIG(1)
    FROM
        @DirectoryTree AS DT
    WHERE
        DT.isFile = 1
        AND DT.subdirectory LIKE @fileMask;

    IF @RC = 0
    BEGIN
        -- Put our process to sleep for a period of time
        WAITFOR DELAY @delayTime;
    END
END

-- at this point, we have either exited due to file found or time expired
IF @RC > 0
BEGIN
    -- Take action when file was found
    PRINT 'Go run SSIS or something';
END
ELSE
BEGIN
    -- Take action for file not delivered in expected timeframe
    PRINT 'Naughty, naughty';
END

要满足您的特定需求,可以像这样设置作业。

  1. 创建工作
  2. 添加到作业服务器
  3. 创建轮询作业步骤。如果失败,请在2分钟内重试最多30次(根据需要更改)
  4. 创建SSIS运行步骤
  5. 定义一个工作计划,该计划从上午6点开始每2分钟运行一次到午夜

在这一点上,我们在这里有皮带,背带和吊带。作业每2分钟启动一次。如果作业已经在运行,则不会发生任何不良情况。一旦工作开始,它就会四处寻找文件。如果超时,则会引发异常(您的TODO),该异常会使代理作业等待2分钟,然后重试30次。

EXEC msdb.dbo.sp_add_job
    @job_name = N'SQL Agent 2 minutes max'
,   @enabled = 1
,   @notify_level_eventlog = 0
,   @notify_level_email = 2
,   @notify_level_page = 2
,   @delete_level = 0
,   @category_name = N'[Uncategorized (Local)]'
,   @job_id = @jobId OUTPUT;

SELECT
    @jobId;
GO

EXEC msdb.dbo.sp_add_jobserver
    @job_name = N'SQL Agent 2 minutes max'
,   @server_name = N'.\DEV2014';
GO

USE msdb;
GO

EXEC msdb.dbo.sp_add_jobstep
    @job_name = N'SQL Agent 2 minutes max'
,   @step_name = N'Polling'
,   @step_id = 1
,   @cmdexec_success_code = 0
,   @on_success_action = 3
,   @on_fail_action = 2
,   @retry_attempts = 30
,   @retry_interval = 2
,   @os_run_priority = 0
,   @subsystem = N'TSQL'
,   @command = N'SELECT 1 AS PasteInTheFullQuery'
,   @database_name = N'master'
,   @flags = 0;
GO

USE msdb;
GO

EXEC msdb.dbo.sp_add_jobstep
    @job_name = N'SQL Agent 2 minutes max'
,   @step_name = N'Run SSIS'
,   @step_id = 2
,   @cmdexec_success_code = 0
,   @on_success_action = 1
,   @on_fail_action = 2
,   @retry_attempts = 0
,   @retry_interval = 0
,   @os_run_priority = 0
,   @subsystem = N'SSIS'
,   @command = N'/ISSERVER "\"\SSISDB\Demo\ProjectDeploymentModel\Package2.dtsx\"" /SERVER "\".\dev2014\"" /Par "\"$ServerOption::LOGGING_LEVEL(Int16)\"";1 /Par "\"$ServerOption::SYNCHRONIZED(Boolean)\"";True /CALLERINFO SQLAGENT /REPORTING E'
,   @database_name = N'master'
,   @flags = 0;
GO

USE msdb;
GO

EXEC msdb.dbo.sp_update_job
    @job_name = N'SQL Agent 2 minutes max'
,   @enabled = 1
,   @start_step_id = 1
,   @notify_level_eventlog = 0
,   @notify_level_email = 2
,   @notify_level_page = 2
,   @delete_level = 0
,   @description = N''
,   @category_name = N'[Uncategorized (Local)]'
,   @notify_email_operator_name = N''
,   @notify_page_operator_name = N'';
GO

USE msdb;
GO

DECLARE @schedule_id int;

EXEC msdb.dbo.sp_add_jobschedule
    @job_name = N'SQL Agent 2 minutes max'
,   @name = N'Every 2 minutes'
,   @enabled = 1
,   @freq_type = 4
,   @freq_interval = 1
,   @freq_subday_type = 4
,   @freq_subday_interval = 2
,   @freq_relative_interval = 0
,   @freq_recurrence_factor = 1
,   @active_start_date = 20181018
,   @active_end_date = 99991231
,   @active_start_time = 60000
,   @active_end_time = 235959
,   @schedule_id = @schedule_id OUTPUT;

SELECT
    @schedule_id;
GO