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 がソフトウェア更新プログラムの説明に使用する 用語 について説明します。