rowversion从0xFF循环递增后跳过整数的原因探究
这个问题其实是SQL Server对rowversion计数器的一个内置特殊规则导致的,我来给你拆解清楚:
SQL Server的rowversion计数器会主动跳过所有低字节全为0的十六进制值,比如0x00、0x100、0x200……直到0x7FFFFFFFFFFFFFFF00这类值。你看到的从0x00000000000007FF直接跳到0x0000000000000801,就是因为中间的0x0000000000000800最后一个字节是00,被判定为需要跳过的预留值。
背后的设计原因
这个规则是为了避免和rowversion的“未初始化”状态或者内部标记混淆。在SQL Server底层逻辑里,全零结尾的rowversion值被预留用于特定场景(比如表示某个对象还未分配过rowversion值),所以计数器会自动跳过这些值,确保生成的所有rowversion都是有效的、可区分的。
验证规则的小测试
你可以再做个验证:当计数器走到0x0000000000000FFF时,下一个生成的值会是0x0000000000001001,绝对会跳过0x0000000000001000——完全符合这个规律。
复现步骤(整理版)
- 创建测试表:
CREATE TABLE [dbo].[TestTable]( [Id] [bigint] IDENTITY(1,1) NOT NULL, [SomeData] [varchar](200) NOT NULL, [RowVersion] [rowversion] NOT NULL ) ON [PRIMARY]
- 执行循环插入生成rowversion:
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
查询结果里就能看到0x00000000000007FF之后直接出现0x0000000000000801,跳过了0x0000000000000800。
补充说明
根据rowversion的官方定义:
数据库中每个包含rowversion列的表执行插入或更新操作时,数据库的计数器都会递增。
这里的“递增”并不是严格的连续整数递增,而是在内部规则约束下的递增——跳过预留的特殊值,保证rowversion的有效性。

内容的提问来源于stack exchange,提问作者wal

