2

正如标题所暗示的,我在数据导入期间遇到了 SSIS 包的问题。我将尽力描述我能做到的最好的需求、采取的方法、问题以及我到目前为止所做的尝试。

需求:将
数据从 Excel 2007 文件(1.000.000 行)导入 SQL 表。
文件是在 UI 的帮助下上传的,因此包必须接收文件路径作为参数
导入不能阻塞 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 语法的帮助

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



更新
虽然手头的问题仍未解决,但我设法找到了解决需求的不同方法。
在我之前的声明中,我说过我不知道如何将参数传递给作业步骤。与此同时,我找到了一种方法。这不是一个真正的直接问题,但它确实解决了我的问题。使用更新所需的作业步骤更新和权限,我设法修改了作业步骤的注释字段

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

由于能够修改作业步骤,我将对包的调用从存储过程移至作业步骤。
需要提醒一件事:要执行从服务器代理打包的 DTS,该步骤必须在 sysadmin 帐户下运行,或者需要代理才能允许执行。



我很感激有关如何处理当前问题的一些提示:我应该将其标记为已回答还是应该让它这样回答最初的问题?

4

2 回答 2

2

根本原因

xp_cmdshell存在一个已知问题,它只允许处理一组双引号参数。

解析度

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

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

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

伪代码大约

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();
于 2013-04-10T18:03:29.530 回答
0

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

于 2013-08-30T17:08:47.507 回答