症状
如果对具有聚集索引或唯一索引的表运行更新,并且更新发生在非主要唯一列上,则更改跟踪记录与更新语句不一致。
例如,假设聚集索引或唯一索引中包含名为“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 | I | NULL | NULL | 5639485628 |
| 1116 | 20 | D | NULL | NULL | 5639485628 |
当列值从较小值更改为较大值 (例如将值从 16 更改为 20) 时,“D”将插入到“I”之前。
| 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 2016 Service Pack 1 的累积更新 9
关于SQL Server生成
SQL Server的每个新版本都包含上一版本中的所有修补程序和安全修补程序。 建议为 SQL Server 安装最新版本:
状态
Microsoft 已确认在 "适用于" 部分中所列的 Microsoft 产品中存在问题。
更多信息
对于已启用更改跟踪的表,当更新在定义为唯一的非主列上时,将两个条目插入到更改跟踪端表中:每个拆分操作的一个条目:插入和删除。
调用 CHANGETABLE 函数来枚举更改时,这些条目按主键值排序,然后聚合操作。 如果更新插入一个较低的值,则首先在侧表中运行“I”操作,然后对“D”操作运行。 这会导致为此行返回不正确的操作。 这是因为“I”后跟“D”聚合为“D”。
由于侧表中只维护主键值,因此不需要有两个单独的条目。 只要主键列未更新,这一点就成立。
此问题已针对非主唯一列修复。 在这种情况下,发生更新时,只有一行是通过将“U”作为更新操作而不是两个具有“D”和“I”的条目来插入的。
参考资料
了解Microsoft用于描述软件更新 的术语 。