現象
クラスター化インデックスまたは一意なインデックスを持つテーブルで更新を実行し、その更新がプライマリ以外の一意の列で実行されると、変更追跡レコードは 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 2014 の最新の累積的な更新プログラム
状態
Microsoft は、これが "適用対象" セクションに記載されている Microsoft 製品の問題であることを確認しました。
詳細情報
変更追跡対応テーブルの場合、一意になるように定義されたプライマリ列以外の列で更新が発生すると、変更追跡サイド テーブルに 2 つのエントリ (挿入と削除の分割操作ごとに 1 つのエントリ) が挿入されます。
変更を列挙するために CHANGETABLE 関数が呼び出されると、これらのエントリは主キー値で並べ替えられ、操作が集計されます。 更新プログラムでより小さい値が挿入される場合、最初にサイド テーブルで "I" 操作が実行され、続いて "D" 操作が実行されます。 これにより、この行に対して誤った操作が返されます。 これは、「D」に続く「I」が「D」として集計されるためです。
サイド テーブルでは主キーの値のみが保持されるため、2 つの個別のエントリを持つ必要はありません。 これは、主キー列が更新されない限り当てはまります。
この問題は、プライマリ以外の一意の列に対して修正されています。 この場合、更新が行われると、"D" と "I" を持つ 2 つのエントリではなく、更新操作として "U" を持つことによって 1 つの行のみが挿入されます。
参考資料
Microsoft がソフトウェア更新プログラムについて説明するために使用する 用語について説明します 。