SQL Server 2016 中的“INSERT EXEC 失败,因为存储过程更改了目标表的架构”错误

本文可帮助你解决由于数据库中使用查询数据存储功能的存储过程定期失败而发生的问题。

原始产品版本: SQL Server 2016
原始 KB 数: 4465511

现象

假设出现了下面这种情景:

  • 你有一个Microsoft SQL Server 2016 数据库,该数据库正在使用查询数据存储功能。

  • 你有一个存储过程,该存储过程使用 INSERT...EXEC 语法调用另一个存储过程。

  • 查询数据存储功能会定期运行自动清理,因为它增加到其配置的最大大小。 此外,查询数据存储状态会从READ_WRITE此更改。READ_ONLY

在此方案中,父存储过程执行会定期失败,并收到如下所示的错误消息:

Msg 556,级别 16,状态 2,LineNumber
由于存储过程改变了目标表的架构,INSERT EXEC 失败。

原因

自动清理过程将计划刷新出查询数据存储。 查询遇到重新编译操作,因为查询数据存储中缺少该计划。 但是,计划仍存在于过程缓存中。 按照设计,当重新编译操作发生时,SQL Server 将引发错误 556,以防止重复执行子过程。 此类重复操作将导致返回不正确的结果。

解决方法

SQL Server 2016 的 Service Pack 信息

此问题已在 SQL Server 的以下 Service Pack 中修复:

适用于 SQL Server 2016 的 Service Pack 3

关于 SQL Server 的 Service Pack:

服务包是累积的。 每个新服务包都包含以前的服务包中的所有修补程序,以及任何新的修补程序。 建议为该服务包应用最新的 Service Pack 和最新的累积更新。 在安装最新的服务包之前,无需安装以前的服务包。 有关最新 Service Pack 和最新累积更新的详细信息,请参阅以下文章中的表 1:

如何确定 SQL Server 及其组件的版本、版本和更新级别

解决方法

若要解决此问题,请执行以下步骤:

  1. 增加查询数据存储的大小。 这将减少查询数据存储清除计划并进入 READ_ONLY 操作模式的频率或可能性。

  2. 将错误处理添加到代码以捕获错误 556,然后重新提交 INSERT EXEC 查询。

  3. 当查询数据存储从中返回状态READ_WRITEREAD_ONLY时清除过程缓存。

其他信息

由于Microsoft SQL Server 2017 中查询数据存储所做的更改,SQL Server 2017 中不会发生此问题。