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

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

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

症状

请考虑以下情况:

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

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

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

在这种情况下,父存储过程执行会定期失败,并且你会收到类似于以下内容的错误消息:

消息 556,级别 16,状态 2,LineNumber
INSERT EXEC 失败,因为存储过程更改了目标表的架构。

原因

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

解决方案

SQL Server 2016 的 Service Pack 信息

以下 service Pack 中修复了此问题,适用于SQL Server:

Service Pack 3 for SQL Server 2016

关于SQL Server的 Service Pack:

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

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

解决方法

若要解决此问题,请按照下列步骤操作:

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

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

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

其他信息

由于对 Microsoft SQL Server 2017 中的查询数据存储进行了更改,因此 2017 SQL Server不会出现此问题。 此问题在 2016 SQL Server不会修复。