通过代码创建和执行的 SSIS 包需要在多次运行后重新启动服务

Posted

技术标签:

【中文标题】通过代码创建和执行的 SSIS 包需要在多次运行后重新启动服务【英文标题】:SSIS Package Created and Executed via Code Requires Service to be Restarted after Multiple Runs 【发布时间】:2021-01-01 14:24:13 【问题描述】:

我们有现有的 C# 代码来动态创建从不同文件读取并进入 SQL Server 2016 数据库的 SSIS 包。它可以满足我们的需要,但偶然发现了一个我们仍然无法解决的问题:无法继续运行 .Execute 命令而无需重新启动我们的自定义 Windows 服务。

目前限制为 2 个文件。如果我们第三次运行调用 Execute 命令的代码,它将根据我们通过 Component 和 Run Event 处理程序记录的内容卡在 post validate 上,并且我们无法继续,直到我们重新启动 Windows 服务和再次运行。我们不能总是重启服务,因为如果我们采用这种方法,可能会中断其他进程。

到目前为止我们已经尝试过的事情:

    提取代码创建的 dtsx 包并尝试在本地使用 dtexec 或 BIDS 运行它。没有出现错误/警告,我们可以不断重复运行同一个包而不会失败。 在本地运行相同的代码。结果与 #1 相同。 在我们的 DBA 的帮助下运行 SQL 跟踪。确认我们没有锁定目标表和数据库本身的查询。我们确实观察到一些 SPID 在第三次运行后被保留,但都处于休眠状态。 修改我们的 RunEventHandler 和 ComponentEventHandler 以记录进程所在的步骤。还尝试通过事件查看器启用日志记录。没有错误,真的只是卡在前面提到的验证后第三次运行。 显式调用 SSIS 处置方法,甚至尝试显式处置连接管理器本身。 使用 DelayValidations 和 ValidateExternalMetadata 属性。

有没有其他人以前遇到过这种情况并且能够弄清楚是什么原因造成的?

【问题讨论】:

关于没有显示代码的代码的问题是出了名的难以解决。为了让我的想法正确,您的服务会识别源文件,创建一个自定义包来摄取它,然后执行它。两个并发执行很好,但是当它拿起第三个文件时,包生成很好,但是在验证步骤触发后运行挂起?或者你是说相同的文件格式,相同的包在第三轮运行时挂起? 是后者。因此,即使我使用相同的文件将相同数量的记录添加到数据库中的同一个表中,它也会在第三次尝试时冻结。 一个处理周期是否包括创建包 + 执行,还是创建包并运行 3 次以重现问题?包裹里有什么特别的吗?只是想了解一个再现 一个处理周期是创建包然后执行。在执行时间的第三个周期冻结。 我今天又进行了一些调试,发现如果我通过 IIS 托管的 Web 应用程序运行相同的代码,问题不会持续存在,所以是的,它与您的最新评论一致。感谢您通过这个问题与我交谈。质疑服务和基于 Web 的应用程序(它们使用相同的用户帐户)之间可能有什么不同,因为它应该只是运行相同的东西。希望我能尽快了解原因。 【参考方案1】:

为了解释最新的评论,我们发现问题源于我们调用单独的 AppDomain 来负责运行作业并因此执行包的事实。创建这个单独的 AppDomain 的方式是通过 CreateInstanceAndUnwrap,使用以下代码:

private AppDomain CreateAppDomain(string applicationName)
    
        var uid = Guid.NewGuid();
        var fi = new FileInfo(Assembly.GetExecutingAssembly().Location);
        var info = new AppDomainSetup
        
            ConfigurationFile = @"D:\Deploy\App\web.config",
            ApplicationBase = @"D:\Deploy\App",
            ApplicationName = applicationName,
            CachePath = fi.Directory.Parent.FullName + @"\Temp",
            ShadowCopyDirectories = @"D:\Deploy\App\bin",
            PrivateBinPath = "bin",
            ShadowCopyFiles = "true"
        ;

        var domain = AppDomain.CreateDomain(uid.ToString(), null, info);
        return domain;
    

我们能够通过对创建的域调用 AppDomain.Unload(domain) 来测试这个理论,虽然我们得到了 DomainUnloadException,但这确实可以防止作业在运行两次后冻结。

我们还没有确切地确定域中的哪些内容被锁定并阻止我们运行该作业两次以上,了解更多相关信息的指导会很有帮助。与此同时,我们目前正在使用这种卸载应用程序域的解决方法。

【讨论】:

以上是关于通过代码创建和执行的 SSIS 包需要在多次运行后重新启动服务的主要内容,如果未能解决你的问题,请参考以下文章

从SQL Server代理作业步骤调用时,SSIS包不会运行

使用 SQL 身份验证执行 SSIS 包

在 SSIS 执行 SQL 任务中捕获错误行

SSIS 包需要很长时间或最终失败

如何设置 SSIS 父包,使 4 个子包可以同时运行,传入不同的参数值?

SSIS 包从文件系统运行