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 情報

この問題は、SQL Server 用の次の Service Pack で修正されています。

SQL Server 2016 用 Service Pack 3

SQL Server のサービス パックについて:

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 のクエリ データ ストアに加えられた変更のため、この問題は SQL Server 2017 では発生しません。