SSIS包在运行时挂起

时间:2013-04-10 08:46:40

标签: sql-server ssis

正如标题所示,我在数据导入过程中遇到SSIS包问题。 我将尽力描述我能满足的最佳需求,采取的方法,问题和我迄今为止所尝试的内容。

需要:
将数据从Excel 2007文件(1.000.000行)导入SQL表。
在UI的帮助下上传文件,因此包必须接收文件路径作为参数
导入不得阻止用户界面 在SQL级别应用的额外业务验证
知道包裹是否失败的可能性 失败后回滚的可能性

方法:
我已经创建了一个SSIS包并在BIDS中成功测试了 创建了一个存储过程,并在xp_cmdshell的帮助下调用了dtexec 创建了一个不阻止UI的工作(并且还能够识别导入/业务需求是否仍在运行中) 填充了一个表来存储包的参数(在我已经完成的研究中,我发现我无法将参数直接传递给作业或作业步骤)

构建对dtexec的调用的代码如下所示

DECLARE @SSIS NVARCHAR(4000) = '';
DECLARE @Params NVARCHAR(4000) = '/set \package.variables[FileName].Value;"\"' + @FileName + '\"" /set \package.variables[ConnectionString].Value;"\"' + @ConnectionString + '\""';
DECLARE @ExePath NVARCHAR(4000) = 'C:\"Program Files (x86)"\"Microsoft SQL Server"\100\DTS\Binn\'

SET @SSIS = @ExePath + 'dtexec /f "' + @PackageName + '" '
SET @SSIS = @SSIS + @Params

DECLARE @ReturnCode int
EXEC @ReturnCode = master..xp_cmdshell @SSIS

以及由xp_cmdshell

运行并生成的行
C:\"Program Files (x86)"\"Microsoft SQL Server"\100\DTS\Binn\dtexec /f "C:\inetpub\wwwroot\pwc\\Import.dtsx" /set \package.variables[FileName].Value;"\"\\<server_name>\upload\Import.xlsx\"" /set \package.variables[ConnectionString].Value;"\"<connection_string>\""


问题:
在保持占用内存(在任务管理器中观察过程)的情况下,在非常长的运行(1h +)之后,程序包似乎挂起并且什么都不做,尽管它应该花费大约25分钟。
所以,我的问题是:
1.什么可能使包装挂起并且无法完成 2.当文件为220mb时,为什么dtexec需要大约2GB的内存(这是出于好奇;我可以忍受内存问题)

我试过的:
在cmd中运行该行。包成功运行,这让我觉得xp_cmdshell是一个问题 我已经读过xp_cmdshell的权限可能有问题所以我当前正在以SQL管理员身份运行该作业 我找到了一些可以解释正在发生的事情,但它涉及从应用程序运行包;如果这是问题,我将非常感谢SQL语法中的一些帮助

非常感谢您帮助我解决这个问题



更新
虽然手头的问题仍然没有解决,但我已经设法找到了解决需求的不同方式 在我之前的陈述中,我说我不知道​​如何将参数传递给作业步骤。与此同时,我找到了办法。它不是一个直接的,但它确实解决了我的问题。 使用job step updatepermissions needed for update,我设法修改了作业步骤的注释字段

EXEC msdb.dbo.sp_update_jobstep
@job_name = N'StartImportFlow',
@step_id = 1,
@command  = <my command> ;

由于能够修改作业步骤,我将包的调用从存储过程移动到作业步骤 有一点需要提醒:要执行从Server Agent打包的DTS,该步骤必须在sysadmin帐户下运行,或者它需要一个代理才能执行。



我会对如何解决当前问题提出一些建议:我应该将其标记为已回答,还是应该让它像这样才能回答最初的问题?

2 个答案:

答案 0 :(得分:2)

根本原因

xp_cmdshell有一个known issue,只允许处理一组双引号参数。

分辨率

  1. 你可以走工作路线。这种方法的缺点是你只能运行一个实例。我不知道UI如何实现,但并发上传可能很难看。

  2. 创建一个运行包的批处理文件。它将采用文件名和连接参数,这可能只会导致传入一组双引号参数。

  3. 我对于不阻止UI的要求感到困惑,但它需要知道包失败。一种选择是让您的UI将所有启动参数写入表中。然后有一个计划的进程来运行每N个时间间隔,它启动具有所述参数的那些包,并将结果写回到该表或另一个表。您也可以直接从UI启动包。虽然您可以使用dtexec,但此时您正在编写自定义代码,只需使用对象模型即可完成。

  4. 伪代码

    using Microsoft.SqlServer.Dts;
    
    string fileName = @"\\network\path\file.dtsx";
    Application app = new Application();
    Package p = app.LoadPackage(fileName, null);
    p.Variables["FileName"].Value = @"\\network\path\file.xlsx";
    p.Variables["ConnectionString"].Value = @"whatever works";
    DTSExecResult results = currentPackage.Execute();
    

答案 1 :(得分:0)

如果在64位计算机上运行此程序包,则使用32位版本的dtexec.exe将导致程序包挂起。使用C:\ Program Files,而不是C:\ Program Files(x86)来获取64位版本。或者只是从SQL代理作业步骤(使用64位版本)执行包。此外,不要在64位计算机上使用执行包实用程序。它使用名为dtexecUI的32位exe。