現象
クラスター化されたインデックスまたは一意のインデックスを持つテーブルで更新を実行し、プライマリ以外の一意の列で更新が行われると、変更追跡レコードは update ステートメントと矛盾します。
たとえば、"column1" という名前の列がクラスター化インデックスまたは一意のインデックスに含まれているとします。 列の値が大きい値から小さい値に変更されると (値を 20 から 16 に変更するなど)、変更追跡側テーブルは、削除操作の前に挿入操作を受け取ります。 たとえば、トランザクション ログ挿入行レコード操作は、行の削除操作の前に受信されるか、"D" の前に "I" が挿入されます。
Sys_change_version |
sys_change_create_version |
sys_change_operation |
sys_change_column |
sys_change_context |
PK_column |
1116 |
19 |
私 |
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 |
私 |
NULL |
NULL |
5639485628 |
原因
この問題は、変更追跡側テーブルの削除と挿入のペア間の順序が正しくないために発生します。
解決方法
この問題の修正プログラムは、SQL Serverの次の更新プログラムに含まれています。
SQL Server 2017 の累積的な更新プログラム 8
SQL Server 2016 Service Pack 1 の累積的な更新プログラム 9
ビルドSQL Serverについて
SQL Serverの各新しいビルドには、前のビルドにあったすべての修正プログラムとセキュリティ修正プログラムが含まれています。 SQL Server用の最新のビルドをインストールすることをお勧めします。
状態
マイクロソフトでは、この問題をこの資料の対象製品として記載されているマイクロソフト製品の問題として認識しています。
詳細情報
変更追跡が有効なテーブルの場合、一意であると定義されている非プライマリ列で更新が発生すると、変更追跡側テーブルに 2 つのエントリが挿入されます。分割アクションごとに 1 つのエントリ、挿入と削除が行われます。
変更を列挙するために CHANGETABLE 関数が呼び出されると、これらのエントリは主キー値で並べ替えられ、操作が集計されます。 更新プログラムが低い値を挿入した場合、最初にサイド テーブルで "I" 操作が実行され、その後に "D" 操作が実行されます。 これにより、この行に対して正しくない操作が返されます。 これは、"I" の後に続く "D" が "D" として集計されるためです。
主キーの値のみがサイド テーブルに保持されるため、2 つの個別のエントリを持つ必要はありません。 これは、主キー列が更新されない限り当てはまります。
この問題は、プライマリ以外の一意の列で修正されています。 この場合、更新が発生すると、"D" と "I" の 2 つのエントリではなく、更新操作として "U" を持つ行が 1 つだけ挿入されます。
参考資料
Microsoft がソフトウェア更新プログラムの説明に使用する 用語 について説明します。