SQL Server RowVersion/时间戳 - 比较

发布于 2024-10-07 18:43:33 字数 302 浏览 1 评论 0原文

我知道 RowVersion 列的值本身并没有什么用处,只是每次更新行时它都会发生变化。但是,我想知道它们对于相对(不平等)比较是否有用。

如果我有一个包含 RowVersion 列的表,则以下任一情况为 true:

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

谢谢。

I know that the value itself for a RowVersion column is not in and of itself useful, except that it changes each time the row is updated. However, I was wondering if they are useful for relative (inequality) comparison.

If I have a table with a RowVersion column, are either of the following true:

  • Will all updates that occur simultaneously (either same update statement or same transaction) have the same value in the RowVersion column?
  • If I do update "A", followed by update "B", will the rows involved in update "B" have a higher value than the rows involved in update "A"?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

烏雲後面有陽光 2024-10-14 18:43:33

来自 MSDN

每个数据库都有一个计数器对于数据库中包含 rowversion 列的表执行的每个插入或更新操作都会递增。该计数器是数据库rowversion。这跟踪数据库内的相对时间,而不是与时钟关联的实际时间。 每次修改或插入具有 rowversion 列的增量 > 数据库 rowversion value 插入到 rowversion 列中。

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

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

对于增量多少的问题,MSDN 指出,“[rowversion] 跟踪数据库内的相对时间”,这表明它不是一个流动的整数增量,而是基于时间。然而,这个“时间”并没有揭示确切的时间,而是相对于其他行插入/修改行的时间。

From MSDN:

Each database has a counter that is incremented for each insert or update operation that is performed on a table that contains a rowversion column within the database. This counter is the database rowversion. This tracks a relative time within a database, not an actual time that can be associated with a clock. Every time that a row with a rowversion column is modified or inserted, the incremented database rowversion value is inserted in the rowversion column.

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

  • As far as I understand, nothing ACTUALLY happens simultaneously in the system. This means that all rowversions should be unique. I venture to say that they would be effectively useless if duplicates were allowed within the same table. Also giving credance to rowversions not being duplicated is MSDN's stance on not using them as primary keys not because it would cause violations, but because it would cause foreign key issues.
  • According to MSDN, "The rowversion data type is just an incrementing number..." so yes, later is larger.

To the question of how much it increments, MSDN states, "[rowversion] tracks a relative time within a database" which indicates that it is not a fluid integer incrementing, but time based. However, this "time" reveals nothing of when exactly, but rather when in relation to other rows a row was inserted/modified.

挽你眉间 2024-10-14 18:43:33

一些附加信息。
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

Some additional information.
RowVersion converts nicely to bigint and thus one can display better readable output when debugging:

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
卸妝后依然美 2024-10-14 18:43:33

需要注意的是,从 SQL Server 2008 开始,timestamp 已被弃用。应改用 rowversion

来自 MSDN 上的此页面

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

Just as a note, timestamp is deprecated in SQL Server 2008 onwards. rowversion should be used instead.

From this page on MSDN:

The timestamp syntax is deprecated. This feature will be removed in a
future version of Microsoft SQL Server. Avoid using this feature in
new development work, and plan to modify applications that currently
use this feature.

笑叹一世浮沉 2024-10-14 18:43:33

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

我最终在我想要数据的表上创建了一个数据库视图,并使用别名列“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();

来获取我想要的内容 - 自上次检查以来所有条目都已更改。

I spent ages trying to sort something out with this - to ask for columns updated after a particular sequence number. The timestamp is really just a sequence number - it's also bigendian when c# functions like BitConverter.ToInt64 want littleendian.

I ended up creating a db view on the table i want data from with an alias column 'SequenceNo'

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

c# Code first sees the view (ie UserV) identically to a normal table

then in my linq I can join the view and parent table and compare with a sequence number

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();

to get what I want - all the entries changed since the last time I checked.

桃扇骨 2024-10-14 18:43:33

是什么让您认为时间戳数据类型是邪恶的?该数据类型对于并发检查非常有用。 Linq-To-SQL 正是出于此目的使用此数据类型。

您的问题的答案:

1) 否。每次更新行时,该值都会更新。如果您要更新该行五次,则每次更新都会增加时间戳值。当然,您意识到“同时发生”的更新实际上并非如此。它们仍然一次只轮流出现一个。

2)是的。

What makes you think Timestamp data types are evil? The data type is very useful for concurrency checking. Linq-To-SQL uses this data type for this very purpose.

The answers to your questions:

1) No. This value is updated each time the row is updated. If you are updating the row say five times, each update will increment the Timestamp value. Of course, you realize that updates that "occur simultaneously" really don't. They still only occur one at a time, in turn.

2) Yes.

你的呼吸 2024-10-14 18:43:33

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

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

Rowversion does break one of the "idealistic" approaches of SQL - that an UPDATE statement is a single, atomic action, and acts as if all UPDATEs (both to all columns within a row, and all rows within the table) occur "at the same time". But in this case, with Rowversion, it is possible to determine that one row was updated at a slightly different time than another.

Note that the order in which rows are updated (by a single update statement) is not guaranteed - it may, by coincidence follow the same order as the clustered key for the table, but I wouldn't count on that being true.

月寒剑心 2024-10-14 18:43:33

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

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

来源:行版本 (Transact-SQL)

To answer part of your question: you can end up with duplicate values according to MSDN:

Duplicate rowversion values can be generated by using the SELECT INTO
statement in which a rowversion column is in the SELECT list. We do
not recommend using rowversion in this manner.

Source: rowversion (Transact-SQL)

静待花开 2024-10-14 18:43:33

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

Every database has a counter that is incremented one by one on every data modification that is done in the database. If the table containing the affected (by update/insert) row contains a timestamp/rowversion column, the current counter value of the database is stored in that column of the updated/inserted record.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文