【问题标题】:SSIS; row redirected to error even after inserting to DBSSIS;即使在插入数据库后,行也重定向到错误
【发布时间】:2015-06-04 00:27:10
【问题描述】:

我有一个 SSIS 包可以将行插入/更新到数据库。首先,我使用查找来检查行是否已插入 DB;如果是,我更新该行,否则插入为新行。

我的问题是插入时,一行插入成功但也重定向到错误。两者怎么可能同时发生?这也发生在某些时候并不总是 - 非常不一致。如何跟踪导致错误的原因?我在这里使用“重定向行”来获取失败的行。

仅当它部署在服务器上时才会发生这种情况。在使用 BIDS 运行我的本地计算机时工作正常。

【问题讨论】:

  • 您的错误输出中是否包含错误描述?源中是否有两条记录导致查找路径将第二条记录视为新记录,但由于 PK/FK 约束而导致插入失败?

标签: ssis ssis-2012


【解决方案1】:

您的 OLE DB 目标可能设置为默认值

快速回顾一下所有这些值的含义

  • 数据访问模式:您通常需要Table or view - fast loadTable or view name variable - fast load,因为这将执行批量插入。非快速加载选择会导致单例插入,对于任何数据量,您都会质疑那些告诉您 SSIS 可以非常快速地加载数据的人的理智。
  • 保持身份:仅当您想明确提供身份种子时才需要这样做
  • 保持空值:这指定是否应允许触发默认值
  • 表锁:抢先锁定表。除非您正在处理 Hekaton 表(新的 SQL Server 2014 糖果),否则触摸表将涉及锁。是的,即使您使用 NOLOCK 提示。插入数据显然会导致锁定,因此我们可以确保我们的 ACID 合规性。 SQL Server 将从一个小锁开始,无论是行级别还是页级别。如果您超过了修改数据的阈值,SQL Server 将升级该锁以封装整个表。这是一种性能优化,因为如果没有其他人在数据中拥有肮脏的小爪子,它会更容易工作。代价是,在此升级期间,我们现在可能必须等待另一个进程完成,这样我们才能获得对表的排他性。如果我们一开始就做大,我们可能会在其他过程开始之前锁定桌子。 - 检查约束:我们是否应该禁用约束值的检查。除非您有一个导入后步骤来确保约束有效,否则不要取消选中此选项。快速加载对域无效的数据是不好的。
  • 每批次的行数:这是作为ROWS_PER_BATCH 值传递给INSERT BULK 语句的值。
  • 最大插入提交大小:FastLoadMaxInsertCommitSize 属性指定提交前事务中应保留的行数。 2005 年的默认值为 0,这意味着所有内容都已提交或不提交。 2008 年+ 20 亿的默认值可能实际上是相同的,具体取决于您的数据量。

那又怎样

您在插入的某处有错误数据。某些原因导致插入失败。它可能是第一行,最后一行,两者或两者之间的某个地方。最终效果是插入本身被回滚。您将包设计为允许将不良数据路由到平面文件,以便数据管理员可以对其进行检查、清理并将其重新插入管道。

那么关键是您需要找到一些值,以提供插入性能大小的最佳平衡,相​​对于 badness 大小,越多越好。为了便于讨论,我们使用5003 的提交大小,因为每个人都喜欢素数,并假设我们的数据源提供了 10009 行数据。其中的三行将违反目标表的完整性,需要由数据管理员检查。

这将导致总共 3 个批次被发送到目的地。结果是以下场景之一

  • 坏行是最后 3 行,导致只有这 3 行被发送到文本文件,10006 行分 2 批提交到表中。
  • 错误行仅存在于完整集中的 1 个中。这将导致 5006 行被写入表,5003 行被发送到我们的文件
  • 在每个提交集中拆分了错误行。这将导致 0 行写入表和我们文件中的所有数据。

我一直觉得墨菲是个乐观主义者,保存错误文件的磁盘会损坏,但我离题了。

理想的做法是减少坏数据可能存在的空间,同时最大限度地增加一次插入的好数据量。事实上,有很多人写过它,但我偏爱“使用 OLE DB 目标进行错误重定向”中概述的方法。

我们将以5003 的初始提交大小执行插入,成功的行将按原样执行。坏行将转到第二个 OLE DB 目标,这一次提交大小较小。您是否应该立即在此处进行单例插入或添加中间批量插入尝试以您的主要提交大小的一半存在意见分歧。在这里您可以评估您的流程并为您的数据找到最佳解决方案。

如果数据仍然无法在单行级别插入,则将其写入错误文件/日志。当您知道将有坏数据时,这种方法允许您以最有效的机制将尽可能多的好数据放入目标表中。

不良数据附录

然而,插入不良数据的最后一种方法是甚至不尝试插入它。如果您知道必须满足外键,请在您的数据流中添加一个查找组件,以确保只有好的值被呈现给插入。 NULL 也一样。您已经在检查您的业务密钥,因此重复应该不是问题。如果列有 Foo 必须以 Pity 开头的约束,则在数据流中检查它。坏行都被分流到派生列任务,该任务添加了业务友好的错误消息,然后它们到达 Union All,然后所有错误都进入错误文件。

我还编写了这个逻辑,其中每个检查都有自己的错误列,并且我只在插入之前拆分出错误数据。这可以防止业务用户修复源数据中的一个错误,而只是得知还有另一个错误。哦,还有另一个,再试一次。是否需要这种级别的数据清理是与您的数据供应商、数据清理人员以及可能是您的老板的对话(因为他们可能想知道您将需要花费多少时间为他们的可怕数据制作这个解决方案继续向你投掷)

参考文献

【讨论】:

    【解决方案2】:

    我注意到,如果您检查锁表并进行更新,您将在数据流中的两个流之间出现死锁。所以我们不检查表锁。性能似乎是一样的。

    【讨论】:

      【解决方案3】:

      我的发现可能会对来这里的人有所帮助..

      @billinkc 发表了广泛的评论;我已经完成了所有这些。好吧,后来在挖掘系统之后,问题就不同了。

      我的 SSIS 包中有脚本任务来执行一些操作。那个使用磁盘中名为 TEMP 的文件夹。触发此 SSIS 的程序也同时使用相同的 TEMP 文件夹。现在没有处理文件读/写异常。 这导致脚本任务失败导致包失败错误。由于脚本任务之前携带的INSERT功能,INSERT成功。后来当脚本失败时,它也将行移动到错误!

      我尝试捕捉这些“文件错误/异常”并且成功了!!

      【讨论】:

      • 很高兴您解决了这个问题。将来,如果您尝试过所有这些事情,请在您的问题中说明,以便我们可以为您遇到的行为寻找替代解释
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-09
      • 1970-01-01
      相关资源
      最近更新 更多