如何让事务和ssis包执行相互等待?

时间:2017-06-01 13:30:38

标签: sql-server tsql ssis transactions service-broker

这是在接收服务代理消息时执行ssis包的简化代码示例,我需要等待所述包的完成更进一步。问题是:事务TR_testSSISOnMsg没有提交,因为“while not exists”循环等待ssis完成,并且ssis执行在SSISDB.catalog.executions中保持“pending”,因为它等待事务提交...所以我最终有两个进程等着彼此完成......交易范围的微调不是我的强项...任何想法?

CREATE PROCEDURE [dbo].[testSSISOnMsg]
AS
BEGIN
    BEGIN TRANSACTION TR_testSSISOnMsg
    WHILE(1=1)
    BEGIN
        DROP TABLE IF EXISTS testLog
        CREATE TABLE testLog (IdLog UNIQUEIDENTIFIER,dateLog DATETIME,msgLog NVARCHAR(100))

        DECLARE @conv_handle UNIQUEIDENTIFIER,
                @msg_type sysname;
        WAITFOR (
            RECEIVE TOP (1)
                    @conv_handle = conversation_handle,
                    @msg_type = message_type_name
                FROM [//SQL2016-DMDI/WorkspaceR/testSSIS/File_DemandeSSIS]
        ), TIMEOUT 1000;

        IF (@@ROWCOUNT = 0)
        BEGIN
            ROLLBACK TRANSACTION TR_testSSISOnMsg;
            BREAK;
        END

        IF @msg_type = N'//SQL2016-DMDI/WorkspaceR/testSSIS/MsgDemandeExec'
        BEGIN
            DECLARE @execution_id bigint,@status int;
            DECLARE @package_name NVARCHAR(100) = N'testPackage.dtsx';

            EXEC SSISDB.catalog.create_execution_VCH
                @folder_name = N'DataScience',
                @project_name = N'ScoresIndexation',
                @package_name = @package_name,
                @execution_id = @execution_id output;

            EXEC SSISDB.catalog.start_execution_VCH @execution_id;

            WHILE NOT EXISTS (SELECT 1 FROM SSISDB.catalog.executions where execution_id = @execution_id and end_time IS NOT NULL)
            BEGIN
                INSERT INTO testLog VALUES(NEWID(),GETDATE(),'waiting')
                WAITFOR DELAY '00:00:30';
            END
        END
        ELSE BEGIN
            END CONVERSATION @conv_handle;
        END
        COMMIT TRANSACTION TR_testSSISOnMsg;
    END
END
GO

3 个答案:

答案 0 :(得分:2)

您想使用[set_execution_parameter_value]将SSIS包设置为运行SYNCHRONIZED。

https://docs.microsoft.com/en-us/sql/integration-services/system-stored-procedures/catalog-set-execution-parameter-value-ssisdb-database

这将在你的create_execution之后和start_execution procs之前进行:

EXEC SSISDB.catalog.create_execution_VCH
    @folder_name = N'DataScience',
    @project_name = N'ScoresIndexation',
    @package_name = @package_name,
    @execution_id = @execution_id output;


EXEC [catalog].[set_execution_parameter_value]
    @executionID,
    @object_type=50, 
    @parameter_name=N'SYNCHRONIZED',
    @parameter_value= 1

EXEC SSISDB.catalog.start_execution_VCH @execution_id;

对于你的测试,我会删除你的waitfor,而不存在select执行表等,因为你不应该需要它们。 Sprocs同步运行,现在你的包也一样,你不需要等待或延迟。当包裹完成后,继续使用您的菜单。

您可能还想查看使用状态而不是结束时间值。

https://docs.microsoft.com/en-us/sql/integration-services/system-views/catalog-executions-ssisdb-database

操作的状态。创建可能的值(1),运行(2),取消(3),失败(4),挂起(5),意外结束(6),成功(7),停止(8)和完成(9)

最后,我注意到你正在使用ssisdb procs的修改版本。由于我们不知道您修改了什么,因此您可能(或可能不)进行了可能导致查询未知问题的更改。在排除故障时请记住。

答案 1 :(得分:0)

您可以通过这种方式等待状态,

-- execute package
EXEC [SSISDB].[catalog].[start_execution] @execution_id;

SET @status = (SELECT [Status] FROM SSISDB.[catalog].[executions]
            WHERE execution_id = @execution_id);

-- check package execution result
-- created (1), running (2), canceled (3), failed (4), pending (5), ended unexpectedly (6), succeeded (7), stopping (8), and completed (9)  
WHILE(@status = 1 OR @status = 2 OR @status = 5 OR @status= 8)
BEGIN

    WAITFOR DELAY '00:00:1'; --'waiting 1 second for Package to finish'

    SET @status = (SELECT [Status] FROM SSISDB.[catalog].[executions]
            WHERE execution_id = @execution_id);
END             

IF @status <> 7 
BEGIN   
    ...
END

答案 2 :(得分:-1)

这不能按原样进行(将事务保持打开状态,直到SSIS完成)-通过单独的外部进程/连接来运行SSIS执行-如果您不提交创建并开始执行的事务,另一个连接将无法看到它以实际运行执行。

我们想做同样的事情...为此,我们要做的是异步启动执行并提交事务,然后在SSIS包的末尾发送一条服务代理消息,说明已完成。在激活过程中,我们使用该消息根据执行的成功或失败来更新状态。请注意,出于相同的原因,您不能使用SYNCHRONIZED -在执行完成之前,我们将无法提交事务,并且直到启动该事务的事务提交为止,该执行才能真正开始运行。 / p>

(请注意,它仍然不是100%防弹的,因为如果SSIS执行开始但随后中止/服务器电源关闭,则由于执行未完成,进程将停止。)