Sql server SSIS包中出错-无法分配环境句柄

Sql server SSIS包中出错-无法分配环境句柄,sql-server,stored-procedures,ssis,sql-server-2008-r2,odbc,Sql Server,Stored Procedures,Ssis,Sql Server 2008 R2,Odbc,我有一个每天运行的SSIS包,它处理给定目录中的CSV文件。每个CSV文件包含约2000行,每行只有一列包含10或11个字符的字符串。该包将数据插入记录集中,在行上循环,并为每行调用最多两个存储过程 通常,每天只有一个CSV文件在相关目录中,因此大约会处理2000行。我又加了10行,总共有20000到25000行。程序包运行时,在最后~2000行期间抛出以下错误: System.Reflection.TargetInvocationException: Exception has been th

我有一个每天运行的SSIS包,它处理给定目录中的CSV文件。每个CSV文件包含约2000行,每行只有一列包含10或11个字符的字符串。该包将数据插入记录集中,在行上循环,并为每行调用最多两个存储过程

通常,每天只有一个CSV文件在相关目录中,因此大约会处理2000行。我又加了10行,总共有20000到25000行。程序包运行时,在最后~2000行期间抛出以下错误:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: ERROR - unable to allocate an environment handle.
   at System.Data.Odbc.OdbcHandle..ctor(SQL_HANDLE handleType, OdbcHandle parentHandle)
   at System.Data.Odbc.OdbcConnection.CreateStatementHandle()
   at System.Data.Odbc.OdbcCommand.GetStatementHandle()
   at System.Data.Odbc.OdbcCommand.ExecuteReaderObject(CommandBehavior behavior, String method, Boolean needReader, Object[] methodArguments, SQL_API odbcApiMethod)
   at System.Data.Odbc.OdbcCommand.ExecuteReaderObject(CommandBehavior behavior, String method, Boolean needReader)
   at System.Data.Odbc.OdbcCommand.ExecuteNonQuery()
   at ST_5d19344133644426ade9d7b3f8a994c2.csproj.ScriptMain.Main()
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
   at Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTATaskScriptingEngine.ExecuteScript()
一些快速的谷歌搜索表明,这个错误与可用内存的问题有关,但我真的没什么意义

因此,我有一些问题:

1) 在尝试调用存储过程的上下文中,此错误的真正含义是什么


2) 我将包的data flow buffer DefaultBufferSize设置保留为默认值(如果我记得的话,为10 MB),但我知道SSI会根据需要更改大小和最大行数?这有关系吗?

我不确定错误是什么意思,但您是否有任何迹象表明可能存在内存压力?odbc驱动程序是32位还是64位

至于如何在SSIS数据流中管理内存,SSIS将使用DefaultBufferMaxSize和DefaultBufferMaxRows作为为每个缓冲区分配多少行的边界。使用默认值,它将最多为10 MB或10000行,以较大者为准,但不超过这些边界。SSIS不会更改这些值,但可以将内存大小增加到100 MB

编辑: 公式的工作原理如下:

RowsPerBuffer = If (DefaultBufferMaxRows * RowSize) > DefaultBufferMaxSize
                    Then (DefaultBufferMaxSize / RowSize)
                    Else DefaultBufferMaxRows
考虑到上面的陈述,您应该看到每个缓冲区有近10k行。 增加默认值将为数据流分配更多内存,因此如果服务器内存严重不足,这可能会对ODBC连接造成压力

每行调用一个或两个进程是一个密集的过程。您可能会考虑将这些值导入到一个分级表中,并使用数据库引擎以一种基于集合的方式执行重载。 编辑: 为了澄清基于集合的方法,我来自SQLETL开发背景,因此我通常考虑如何快速处理大量数据。此外,我还想到了如何在满足完整需求的同时以最少的开发量完成这项工作。因此,基本的经验法则是:

  • 尽可能使用SSI现成组件
  • 使包小,可测试的单位
  • 尽可能避免逐行操作
  • 对数据进行分级,以便利用数据库服务器执行其更擅长的任务,如合并数据集和排序数据
因此,如果您要为每一行调用一个proc,这意味着SQL中的数据对该行集很重要。您可以执行以下操作:

  • 添加一个foreach循环来处理每个文件,并将数据流添加到此循环中
  • 用标准平面文件源组件替换自定义脚本源
  • 将数据按原样转移到SQL表中
  • 将proc逻辑替换为SQL查询,该查询将数据集连接在一起,以获得所需的最终结果集。这个新任务可以进入它自己的存储过程
  • foreach循环完成后,在SSIS中的t-SQL任务中调用上述查询

最终的结果是,您将拥有一个性能更好、更易于维护的软件包。

它是一个64位驱动程序。那么,如果SSI没有达到大小限制,它会超过最大行设置吗?你能详细说明你的最后一个建议吗?不,SSI不会超过这两个限制。我将更新我的响应,以使其更清楚,以及我的意思,作为替代。我想我应该提到的是,始终被调用的存储过程,将行中的字符串作为参数,并返回另一个字符串(如果返回了任何内容,则将该字符串传递给第二个proc调用)。我想我明白了你的意思,而不是每行获取数据,我可以在一次调用中获得我需要的所有数据。我从中获取数据的数据库也不在SQL Server中,它位于远程服务器上。我可以对远程表进行连接吗?@ScottOliver,它开始变得有点难看,这取决于您检索的数据量、数据更改的频率以及过程中的逻辑有多复杂。但也有一些选择-本地转移远程数据并使用我已经概述的过程,在SSI中使用合并连接和条件拆分将数据放在一起,或者使用链接服务器。是的,我觉得我需要克服很多限制。谢谢你的建议,我以后可能会这么做。