每个数据库都有一个计数器,该计数器针对在数据库中包含rowversion列的表上执行的每个插入或更新操作递增。
然而,当从FF循环回到01时,这个'增量'会跳过一个整数。例如
0x00000000000007FF
0x0000000000000801
要重现,请创建一个表
CREATE TABLE [dbo].[TestTable](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[SomeData] [varchar](200) NOT NULL,
[RowVersion] [rowversion] not null
) ON [PRIMARY]
现在添加一些插页:
DECLARE @i INT = 0
WHILE @i < 256
BEGIN
SET @i = @i + 1
INSERT INTO [TestTable] ([SomeData]) VALUES (CONVERT(VARCHAR(255), NEWID()))
END
查看数据:
select * from [TestTable] order by [RowVersion] asc
根据您是否使用过rowversion
,数据会有所不同
在这种情况下我们看到2047(0x00000000000007FF)跳转到2049(0x0000000000000801)
为什么会这样?
答案 0 :(得分:2)
引用的文档提到rowversion值是唯一的,二进制的和递增的。它并没有说会有差距。该值旨在用于乐观并发验证,因此间隙对于此目的无关紧要。
答案 1 :(得分:0)
这是rowversion(timestamp)的内部实现。该实施允许设计上的差距。
例如,让我们看看数据库备份/恢复如何影响它。
最大rowversion的值存储在数据库引导页面中。生成每个新的rowversion时,该值不会更改。相反,SQL引擎保留了几千行版本并对其进行更新,例如从20,000到24,000。如果还原数据库或数据库脱机,则会丢失20,000..24,000的范围。新行版本将从24,000
开始因此,您的代码绝不应该依赖于没有间隙的假设。
您可以检查最后保存的rowverion值:
DBCC TRACEON (3604);
DBCC DBINFO ('db-name')
并寻找'dbi_maxDbTimestamp'