我目前正在将我们的数据仓库从 SQL 2012 升级到 SQL 2016。我的旧 DW 和新 DW 并行运行。
我的 ETL 流程(由第三方在 SSIS 中开发的框架)在 2012 年成功运行了 2 年多,但在 2016 年失败了。到目前为止,数据库和 ETL 流程是相同的。
两台服务器都是在 VMWare 上运行的虚拟机。旧服务器是 Win 2008,具有 24Gb 的 RAM。SQL 2012 标准。最大内存设置为 16Gb。新服务器是 Win 2012,具有 64Gb 的 RAM。SQL 2016 开发。最大内存设置为 50Gb。新 DW 正在运行 v13.0.1601.5 RTM 开发人员版(64 位)。
在运行我的 ETL 过程时,使用 SQL 合并到维度或事实表的加载步骤失败并出现以下错误。
全文:
描述: SQL Server 断言: 文件: , line=951 断言失败 = 'IS_OFF (BUF_MINLOGGED, m_buf->bstat) || pageModifyType != PageModifyType_Contents || GetPagePtr ()->IsTextPage ()'。此错误可能与时间有关。如果重新运行语句后错误仍然存在,请使用 DBCC CHECKDB 检查数据库的结构完整性,或重新启动服务器以确保内存中的数据结构没有损坏。
按照建议,我运行了 DBCC,没有发现任何错误。我也重新启动了 SQL。然后我重新启动了 ETL 过程并得到了同样的错误。
我对这个错误的搜索表明这是SQL 2008、2012 和 2014 中的已知错误,并在后续的修补程序和累积更新中修复。所以我有点惊讶地看到它在 2016 年重新出现。
我发现的链接说,如果数据库处于简单或批量日志恢复模式,它会在尝试插入时影响 SSIS。(我在简单恢复模式下运行)
建议的解决方法是将 Db 恢复模式更改为 FULL。我已经尝试过了,它可以工作,但它不是数据仓库的解决方案。
2016年有没有人遇到过这种情况?
任何人都可以建议替代解决方法吗?
更新:
26/7/2016:我应用了关键更新 KB3164398 (v13.0.1708.0),但问题仍然存在。
27/7/2016:我已应用累积更新 CU1 KB3164674 (v13.0.2149.0)。
2016 年 3 月 8 日:我们最小的立方体在一夜之间发生错误。CU1 没有解决这个问题。今天我报告了 MS Connect 上的错误,并且我还记录了与 Microsoft 的支持电话。
2016 年 12 月 8 日:MS-Support 最初做出了回应,但回应是“我们没有解决方案”。支持人员将与他的同事讨论并回复我。8天后我没有他的消息。
虽然我没有“修复”,但我们确实找到了适合我们的解决方法。请参阅我发布的答案。
2016 年 9 月 29 日。我上周申请了CU2。在星期四,我们不小心运行了旧版本的合并,它再次失败并出现同样的错误。所以.. CU2 也没有修复它。
23/1/2017:我应用了2016 SP1 CU1,我相信这已经解决了这个问题。特别是 KB3205964
查看 KB,您有几个选项/解决方法:
MERGE
命令?这里的“多个 BULK INSERT”是什么意思?有没有办法将您的方法转换为单个 BULK INSERT,例如一次一个?例如,在 SSIS 中,您可以将“MaxConcurrentExecutables”临时设置为 1,看看是否有帮助。将其绑定到配置变量,以便您以后可以将其更改回来。显然它会减慢速度,但您更喜欢 ETL 完成而不是快速失败。并行处理是一种很好的模式,也是 SSIS 的真正优势,但你只能与最慢的组件一样快;假设你有 10 个维度需要一分钟,一个事实需要一个小时,你的 ETL 在一小时内并行运行或 1 小时 10 分钟连续运行。MERGE
很好,但确实有一些问题。您可以考虑转换回INSERT
/UPDATE
。你也应该根据这里HOLDLOCK
使用with 。你用那个提示吗?如果你这样做,对这个问题有什么影响吗?我们在早期的 SQL 2014 构建中遇到了一个问题,在列存储中使用可组合 DML(子句)导致了这种断言——我让他们将列存储索引从维度中删除,他们在没有告诉我的情况下添加了这些索引。MERGE
MERGE
OUTPUT
祝你好运。
我相信这已在 2016 SP1 CU1 中得到解决。
具体由KB3205964
通过为 MSSQL2016 应用累积更新 1 (CU1) 可以解决此问题,请参阅链接 https://support.microsoft.com/en-us/kb/3164674
我相信我们已经找到了另一种解决方法。我发布了我的答案,因为我认为它可能有用,并且与 wBob 的建议有很大不同。
我们更改了合并语句的插入部分,使其插入临时表而不是原始目标。
一旦合并语句执行,我们就从#table 插入到目标中。
这并不理想,但至少合并仍然通过标记已停用/过期的行来处理“更新插入”的复杂性。
与将合并完全重写为单独的插入和更新相比,我们发现这是一个可以接受的权衡。