KB4135113 - 修正: SQL Server のクラスター化インデックスまたは一意インデックスを持つテーブルの更新中に、変更追跡レコードに一貫性がありません

適用先
SQL Server 2016 Developer - duplicate (do not use) SQL Server 2016 Enterprise - duplicate (do not use) SQL Server 2016 Enterprise Core - duplicate (do not use) SQL Server 2016 Standard - duplicate (do not use) SQL Server 2014 Service Pack 2 - duplicate (do not use) SQL Server 2014 Developer - duplicate (do not use) SQL Server 2014 Enterprise - duplicate (do not use) SQL Server 2014 Enterprise Core - duplicate (do not use) SQL Server 2014 Standard - duplicate (do not use) SQL Server 2017 Developer on Windows SQL Server 2017 Enterprise on Windows SQL Server 2017 Enterprise Core on Windows SQL Server 2017 Standard on Windows

現象

クラスター化インデックスまたは一意なインデックスを持つテーブルで更新を実行し、その更新がプライマリ以外の一意の列で実行されると、変更追跡レコードは update ステートメントと矛盾します。

たとえば、"column1" という名前の列がクラスター化インデックスまたは固有インデックスに含まれているとします。 列の値が大きい値から小さい値に変更されると (値を 20 から 16 に変更するなど)、変更追跡サイド テーブルは削除操作の前に挿入操作を受け取ります。 たとえば、トランザクション ログの行レコードの挿入操作を行の削除操作の前に受信したり、"I" を "D" の前に挿入したりします。

Sys_change_version sys_change_create_version sys_change_operation sys_change_column sys_change_context PK_column
1116 19 I NULL NULL 5639485628
1116 20 D NULL NULL 5639485628

列の値を小さい値から大きな値に変更した場合 (値を 16 から 20 に変更するなど)、"I" の前に "D" が挿入されます。

Sys_change_version sys_change_create_version sys_change_operation sys_change_column sys_change_context PK_column
1126 32 D NULL NULL 5639485628
1126 33 I NULL NULL 5639485628

原因

この問題は、変更追跡サイド テーブルの削除/挿入ペアの順序が正しくないために発生します。

解決策

この問題の修正プログラムは、次の SQL Server の更新プログラムに含まれています。

SQL Server 2017 の累積的な更新プログラム 8

SQL Server 2016 Service Pack 1 の累積的な更新プログラム 9

SQL Server 2014 SP2 の累積的な更新プログラム 12

SQL Server ビルドについて

SQL Server の新しいビルドには、以前のビルドであったすべての修正プログラムとセキュリティ修正プログラムが含まれています。 SQL Server の最新ビルドをインストールすることをお勧めします。

SQL Server 2017 の最新の累積的な更新プログラム

SQL Server 2016 の最新ビルド

SQL Server 2014 の最新の累積的な更新プログラム

状態

Microsoft は、これが "適用対象" セクションに記載されている Microsoft 製品の問題であることを確認しました。

詳細情報

変更追跡対応テーブルの場合、一意になるように定義されたプライマリ列以外の列で更新が発生すると、変更追跡サイド テーブルに 2 つのエントリ (挿入と削除の分割操作ごとに 1 つのエントリ) が挿入されます。

変更を列挙するために CHANGETABLE 関数が呼び出されると、これらのエントリは主キー値で並べ替えられ、操作が集計されます。 更新プログラムでより小さい値が挿入される場合、最初にサイド テーブルで "I" 操作が実行され、続いて "D" 操作が実行されます。 これにより、この行に対して誤った操作が返されます。 これは、「D」に続く「I」が「D」として集計されるためです。

サイド テーブルでは主キーの値のみが保持されるため、2 つの個別のエントリを持つ必要はありません。 これは、主キー列が更新されない限り当てはまります。

この問題は、プライマリ以外の一意の列に対して修正されています。 この場合、更新が行われると、"D" と "I" を持つ 2 つのエントリではなく、更新操作として "U" を持つことによって 1 つの行のみが挿入されます。

参考資料

Microsoft がソフトウェア更新プログラムについて説明するために使用する 用語について説明します 。