現象
クラスター化インデックスまたは一意のインデックスを持つテーブルに対して更新を実行し、プライマリ以外の一意の列で更新が行われると、変更追跡レコードは 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 がソフトウェア更新プログラムの説明に使用する 用語 について説明します。