29

我知道RowVersion列的值本身并没有用,除了每次更新行时它都会改变。但是,我想知道它们是否对相对(不等式)比较有用。

如果我有一个带有RowVersion列的表,则以下任一情况为真:

  • 同时发生的所有更新(相同的更新语句或相同的事务)在RowVersion列中是否具有相同的值?
  • 如果我更新“A”,然后更新“B”,更新“B”中涉及的行是否会比更新“A”中涉及的行具有更高的值?

谢谢。

4

8 回答 8

39

来自 MSDN

每个数据库都有一个计数器,每次对包含数据库列的表执行插入或更新操作时,该计数器都会递增。rowversion这个计数器就是数据库rowversion。这跟踪数据库中的相对时间,而不是可以与时钟关联的实际时间。每次修改或插入带有列的行时,都会将递增的数据库插入该列中。rowversionrowversion rowversion

http://msdn.microsoft.com/en-us/library/ms182776.aspx

  • 据我了解,系统中实际上没有同时发生任何事情。这意味着所有rowversions 都应该是唯一的。我冒昧地说,如果在同一个表中允许重复,它们实际上将毫无用处。同样让人相信rowversions 不会被复制的是 MSDN 关于不将它们用作主键的立场,不是因为它会导致违规,而是因为它会导致外键问题。
  • 根据 MSDN,“rowversion 数据类型只是一个递增的数字......”所以是的,后来更大。

对于增量多少的问题,MSDN 指出,“[ rowversion] 跟踪数据库中的相对时间”,这表明它不是流体整数增量,而是基于时间的。然而,这个“时间”没有透露什么时候准确,而是什么时候插入/修改了与其他行相关的行。

于 2010-12-17T13:36:34.457 回答
13

一些额外的信息。RowVersion 可以很好地转换为 bigint,因此在调试时可以显示更好的可读输出:

CREATE TABLE [dbo].[T1](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Value] [nvarchar](50) NULL,
    [RowVer] [timestamp] NOT NULL
) 

insert into t1 ([value]) values ('a')
insert into t1 ([value]) values ('b')
insert into t1 ([value]) values ('c')
select Id, Value,CONVERT(bigint,rowver)as RowVer from t1
update t1 set [value] = 'x' where id = 3
select Id, Value,CONVERT(bigint,rowver)as RowVer from t1
update t1 set [value] = 'y' 
select Id, Value,CONVERT(bigint,rowver)as RowVer from t1

Id  Value   RowVer
1   a   2037
2   b   2038
3   c   2039

Id  Value   RowVer
1   a   2037
2   b   2038
3   x   2040

Id  Value   RowVer
1   y   2041
2   y   2042
3   y   2043
于 2011-02-19T12:45:24.653 回答
6

我花了很长时间试图解决这个问题 - 要求在特定序列号之后更新列。时间戳实际上只是一个序列号 - 当像 BitConverter.ToInt64 这样的 c# 函数需要 littleendian 时,它也是 bigendian。

我最终在我想要使用别名列“SequenceNo”的数据的表上创建了一个数据库视图

SELECT     ID, CONVERT(bigint, Timestamp) AS SequenceNo
FROM         dbo.[User]

c#代码首先看到视图(即UserV)与普通表相同

然后在我的 linq 中,我可以加入视图和父表并与序列号进行比较

var users =  (from u in context.GetTable<User>()
                join uv in context.GetTable<UserV>() on u.ID equals uv.ID
                where mysequenceNo < uv.SequenceNo
                orderby uv.SequenceNo
                select u).ToList();

得到我想要的 - 自上次检查以来所有条目都发生了变化。

于 2014-03-18T15:37:58.580 回答
5

是什么让您认为 Timestamp 数据类型是邪恶的?数据类型对于并发检查非常有用。Linq-To-SQL 正是出于这个目的使用这种数据类型。

您的问题的答案:

1) 否。每次更新行时都会更新此值。如果您将行更新五次,则每次更新都会增加 Timestamp 值。当然,您意识到“同时发生”的更新实际上不会。反过来,它们仍然一次只出现一个。

2) 是的。

于 2010-12-17T13:28:10.463 回答
5

请注意,timestamp从 SQL Server 2008 起已弃用。rowversion应改为使用。

从MSDN 上的这个页面:

时间戳语法已弃用。此功能将在 Microsoft SQL Server 的未来版本中删除。避免在新的开发工作中使用此功能,并计划修改当前使用此功能的应用程序。

于 2012-07-04T12:05:12.547 回答
3

Rowversion 确实打破了 SQL 的“理想主义”方法之一 - UPDATE 语句是一个单一的原子操作,并且就像所有 UPDATE(对一行中的所有列以及表中的所有行)都发生在“同时”。但是在这种情况下,使用 Rowversion,可以确定一行的更新时间与另一行略有不同。

请注意,不能保证更新行的顺序(通过单个更新语句) - 巧合的是,它可能遵循与表的聚集键相同的顺序,但我不会指望这是真的。

于 2010-12-17T14:05:28.680 回答
2

要回答您的部分问题:根据 MSDN,您最终可能会得到重复的值:

可以使用 SELECT INTO 语句生成重复的 rowversion 值,其中 rowversion 列位于 SELECT 列表中。我们不建议以这种方式使用 rowversion。

来源:rowversion (Transact-SQL)

于 2014-01-14T11:45:03.610 回答
0

每个数据库都有一个计数器,该计数器在数据库中完成的每一次数据修改时都会递增。如果包含受影响(通过更新/插入)行的表包含时间戳/行版本列,则数据库的当前计数器值存储在更新/插入记录的该列中。

于 2011-04-15T16:32:25.700 回答