【问题标题】:SQL Agent job failure with SSIS package to Access DB使用 SSIS 包访问数据库的 SQL 代理作业失败
【发布时间】:2017-03-17 11:06:23
【问题描述】:

我有一个运行脚本任务的 SSIS 包(主要是,还有一些其他的东西)。脚本任务使用 OleDB 连接连接到 Access 数据库。这是 Microsoft Jet 4.0 连接。我已经安装了驱动程序。但它不会通过代理帐户在 SQL 代理中运行。它将直接从 Visual Studio 和包商店正常运行。事实上,当我以代理绑定的特殊帐户登录时,它在这两个地方都运行良好。但是当我通过 SQL Server 代理运行时,我得到了可怕的“未指定错误”OleDbException。

脚本任务的相关代码:

// class field
private string accessConnectionStringTemplate = "Data Source=\"{0}\";Provider=Microsoft.Jet.OLEDB.4.0;";

// in method that connects to database
Print(file, "Connection string: " + string.Format(accessConnectionStringTemplate, file.FileName));
// outputs: Data Source = "\Path\To\File";Provider=Microsoft.Jet.OLEDB.4.0"
using(access = new OleDbConnection(string.Format(accessConnectionStringTemplate, file.FileName))) {
     access.Open();
     // other code
}

通过 SQL 代理作业历史记录的错误消息:

Started:  12:35:10 PM
Error: 2016-11-03 12:35:33.51
   Code: 0x00000000
   Source: Import Files Main
   Description: Exception: Unspecified error
End Error
Error: 2016-11-03 12:35:33.51
   Code: 0x00000000
   Source: Import Files Main
   Description:    at System.Data.OleDb.OleDbConnectionInternal..ctor(OleDbConnectionString constr, OleDbConnection connection)
   at System.Data.OleDb.OleDbConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject)
   at System.Data.ProviderBase.DbConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionInternal.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.OleDb.OleDbConnection.Open()
   at ST_cc0028a4b56242909c2eae546a807995.csproj.ScriptMain.ImportFile(AccessFile file, DateTime startRecordDate, DateTime endRecordDate, List`1 accessTables, Boolean includeTransactionTables, List`1 specifiedTableList)
   at ST_cc0028a4b56242909c2eae546a807995.csproj.ScriptMain.Main()
End Error
Error: 2016-11-03 12:35:33.51
   Code: 0x00000006
   Source: Import Files 
   Description: The script returned a failure result.
End Error

我已经确定的一些事情:

  • Access 驱动程序已安装并在 SQL 代理所在的服务器上运行。我通过在 VS 中作为我的帐户和代理的帐户运行包来验证这一点,没有任何问题。
  • 代理帐户有权访问相关文件。同样,通过以代理帐户登录服务器进行验证。该文件位于网络共享上,但路径被指定为 UNC 路径。
  • 代理帐户有权访问属于此操作的其他数据库,以排除任何其他潜在的错误来源。
  • 从包存储运行包(通过 SSMS),因为我的帐户和代理的帐户都有效。我在数据库服务器上执行此操作以确保。

在我在互联网上看到的其他问题中,这通常是驱动程序的问题。在这种情况下,我不确定它是怎么回事。

我很乐意提供更多信息来帮助其他诊断。我自己完全不确定为什么这不起作用。

【问题讨论】:

  • 奇怪,文件是否以任何方式打开或锁定?
  • @Siyual:不是。而且由于我能够在 SQL 代理之外运行它,所以这似乎不是问题。我想可能有人在我运行代理作业时打开了它,而在其他任何时候都没有,但这似乎不太可能。
  • 嗯 - 这是一个赃物:名义上,连接字符串参数是用分号分隔的,不喜欢参数周围的引号 - 即使是带有嵌入空格的参数。试着把引号去掉。这不是一个踢球者吗?
  • 您是否尝试过更改BufferTEMPstorage 路径和BlobTempstoragepathsqlserverscribbles.com/2013/05/07/… ?
  • @p2k:在 C:\Users\SQLSERVERAGENT\AppData\Local\Temp 目录中授予我的代理帐户权限确实允许它运行。然而,这感觉就像一个黑客。我没有数据流任务,因此无法更改这些变量(它们似乎不存在于脚本任务中)。

标签: sql-server ssis oledb sql-agent


【解决方案1】:

事实证明,问题在于 Jet 提供程序试图写入 SQL 代理用户的临时目录,即使该任务是在以不同用户身份运行的情况下运行的。这似乎是 Windows 模拟系统的一项功能,它不会更改用户配置文件,只会更改用户令牌。我最终得到了这段代码:

var tempPath = Path.GetTempPath().Replace("\\SQLSERVERAGENT\\", "\\" + Environment.UserName + "\\");
Environment.SetEnvironmentVariable("TEMP", tempPath);
Environment.SetEnvironmentVariable("TMP", tempPath);

这并不理想,但它有效。这意味着我不必授予 SQL 代理的临时目录的权限。只需更改此代码。

遗憾的是,似乎无法更改 ODBC 驱动程序放置其临时文件的位置。

编辑:对于带有 Excel 源的常规数据流包,我也遇到了这个问题。在这种情况下,我别无选择,只能为我的代理用户帐户授予对 SQL 代理临时目录的访问权限。如果我也能想出一个解决方法,我会发布它。

【讨论】:

    【解决方案2】:

    我建议尝试几件事:

    1. 尝试使用 cmd 模式执行您的包,即使用 SQL 代理中的 dtexce.exe 语法(同时使用 32 位和 64 位选项)。

    2. 将服务帐户(帐户 SQL 代理正在运行)添加到 DCOM component for Integration Service。如果允许,请将 SQL 代理服务帐户更改为代理帐户(用于测试)。

    3. 使用代理帐户执行所有操作,即使用代理帐户部署包并将作业所有者设置为代理帐户(在 SQL 代理中)。使用代理帐户创建作业。

    4. 如果您的代理帐户或 SQL 代理服务帐户有任何错误,请检查窗口 event viewer

    5. 如果您使用 SQL Server 2012 或更高版本部署包,请尝试使用集成服务目录。

    【讨论】:

    • 程序包正在运行并执行其他操作,它只是无法打开与此 Access 数据库的连接作为其中间步骤之一。我可以尝试做一些这样的事情,但它们似乎与我的问题几乎无关。
    • 您的程序包仅在 SQL 代理作业中失败。因此,可能专注于 SQL 代理服务帐户设置(如权限/访问)会有所帮助。代理帐户似乎没有问题(根据您的描述)。
    • 它(据说)作为我的代理帐户运行,而不是作为我从不使用的 SQL 代理服务帐户运行。
    • 尽管我的工作配置了不同的代理帐户,但由于我的代理帐户,我也遇到了类似的问题。
    • 我尝试了所有这些方法,得到了完全相同的结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-30
    • 2021-12-01
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多