【问题标题】:How to keep transaction and ssis package execution to wait for each other?如何保持事务和 ssis 包执行相互等待?
【发布时间】:2017-06-01 13:30:37
【问题描述】:

这是一个简化的代码示例,它在接收到服务代理消息时执行 ssis 包,我需要等待所述包的完成才能走得更远。问题是:事务 TR_testSISOnMsg 没有提交,因为“while not exists”循环等待 ssis 完成,并且 ssis 执行在 SSISDB.catalog.executions 中保持“挂起”,因为它正在等待事务提交......所以我最终有两个进程等待对方完成......事务范围的微调不是我的强项......有什么想法吗?

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

【问题讨论】:

  • 创建一个 SQL Server 代理作业并让接收到消息开始作业不是更简单吗?然后你可以在作业中创建单独的步骤,它会为你处理完成。
  • 我有一个 SQL Server 代理来“cron”这一切,老实说,我在同一个过程中使用:Service Broker、SSIS 和 SQL Server R 服务......我是不确定在中间添加更多 SQL Server 代理作业会“更简单”:D
  • 不添加作业添加步骤...

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


【解决方案1】:

你可以这样等待状态,

-- 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

【讨论】:

  • 如何改变我等待 SSIS 包完成的方式将解决我的事务问题?
【解决方案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;

对于您的测试,我会删除您的等待,而从执行表中选择不存在等,因为您不应该需要它们。 Sprocs 同步运行,现在您的包也同步运行,您不需要任何等待或延迟。包完成后,继续使用您的 sproc。

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

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 的修改版本。由于我们不知道您修改了什么,您可能(也可能没有)进行了更改,这些更改可能会导致您的查询出现未知问题。在进行故障排除时请牢记。

【讨论】:

  • 感谢您的回答。我需要“虽然不存在”,因为在“完整”过程中(这是一个用于测试的简化过程),一旦 ssis 成功加载数据,我将在服务代理会话上发送应答消息以触发另一个存储过程处理上述数据。另外,我在 end_time 上使用了测试,因为我稍后也在存储过程中检查了状态,并且我想跳过创建、运行等没有结束时间的案例。
  • 好吧,这是有道理的。我的环境中有类似的过程。我们使用表类型来“排队”所有必要的 SSIS 包(有时只有 1 个,有时更多)及其相关参数,并在 SYNC 中运行它们。希望这可以帮助您解决问题!
  • 不幸的是,我刚刚测试了添加 SYNCHRONIZED 参数,我得到了相同的锁。
  • 我什至没有注意到您将整个事物包装在事务中。进程在 sp_who2 中是否死锁?使用事务回滚所有内容(包括日志记录)有什么需要?这可能是相关的support.microsoft.com/en-us/help/2699720/…
  • 我不是事务专家,我见过的每个服务代理的使用示例都以这种方式使用它们,所以我也这样做了,我认为如果需要的话,可以方便地清理对话中的所有内容防止队列中的消息“无限循环”。
【解决方案3】:

这不能按原样工作(在 SSIS 完成之前保持事务打开)- 通过单独的外部进程/连接运行 SSIS 执行-如果您不提交创建和启动执行的事务,为了实际运行执行,其他连接将无法看到它。

我们想做同样的事情……我们要做的是异步启动执行并提交事务,并在 SSIS 包结束时发送一条服务代理消息,说明它已完成。在激活过程中,我们使用该消息根据执行的成功或失败来更新状态。请注意,出于同样的原因,您不能使用 SYNCHRONIZED - 在执行完成之前我们无法提交事务,并且在启动它的事务提交之前,执行无法开始实际运行。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-05
    相关资源
    最近更新 更多