0

在阅读此示例之前,我可以自己理解 rowversion,它反映了记录上最后更新的时间戳。我想它的用法是这样的:首先读取一条记录后,应该达到rowversion列的值。然后在更新该记录之前,应根据从数据库中获取的当前 rowversion 值(在更新前的时间)检查本地存储的 rowversion 值,如果它们不相等,则意味着另一个用户和当前应用程序进行了一些更新应该用自己的策略来处理这种并发情况。

但是,我认为以下示例使问题过于复杂,或者甚至可能是错误的或解释不善(因此会导致混淆):

CREATE TABLE MyTest (myKey int PRIMARY KEY
,myValue int, RV rowversion);
GO 
INSERT INTO MyTest (myKey, myValue) VALUES (1, 0);
GO 
INSERT INTO MyTest (myKey, myValue) VALUES (2, 0);
GO

DECLARE @t TABLE (myKey int);
UPDATE MyTest
SET myValue = 2 OUTPUT inserted.myKey INTO @t(myKey) 
WHERE myKey = 1 AND RV = myValue;

IF (SELECT COUNT(*) FROM @t) = 0
BEGIN
    RAISERROR ('error changing row with myKey = %d'
        ,16 -- Severity.
        ,1 -- State 
        ,1) -- myKey that was changed 
END;

我注意到myValue这里,它被设置为2并在 WHERE 子句中用于检查RV列。据我了解,rowversion 列显然是RV,但随后它解释了这一点:

myValue 是表示您最后一次读取该行的行的 rowversion 列值。此值必须替换为实际的 rowversion 值

我认为myValue这里与rowversion没有任何关系,它应该被视为用户数据。所以有了这样的解释,MyTest表有 2 个 rowversion 列?whilemyValue显然被声明为int?

我能想到的一种可能性是myValue在 WHERE 条件下的理解不同(这意味着它不是myValueSET 子句中的),它可能只是一个占位符,例如RV之前读取记录时的读取值。只有这种可能性对我来说才有意义。

所以据我了解,这个例子应该是这样的:

SET myValue = 2 OUTPUT inserted.myKey INTO @t(myKey) 
WHERE myKey = 1 AND RV = rowVersionValueFromTheLastTimeReading

我以前听说过,timestamprowversion对我来说相当新,一旦我尝试找到更多关于它的信息,我发现这个例子让我很困惑。你对此有什么想法?还是我根本不明白 rowversion 的一些神秘用法?谢谢。

4

2 回答 2

1

联机丛书中的示例不正确。我看到该主题的社区评论中提到了这一点。

下面的代码展示了如何使用rowversion来实现乐观并发。当数据呈现给用户进行更新然后修改时,通常会使用这种方法。

DECLARE
     @MyKey int = 1
    ,@NewMyValue int = 1
    ,@OriginalMyValue int
    ,@OriginalRV rowversion

--get original data, including rowversion
SELECT 
      @OriginalMyValue = myValue
    , @OriginalRV = RV
FROM dbo.MyTest
WHERE myKey = 1;

--check original rowversion value when updating row
UPDATE dbo.MyTest
SET myValue = @NewMyValue
WHERE
    myKey = 1
    AND RV = @OriginalRV;

--optimistic concurrency violation
IF @@ROWCOUNT = 0
    RAISEERROR ('Data was updated or deleted by another user.', 16, 1);

或者,可以检查原始数据值而不是rowversion. 但是,如果您有很多列并且需要检查NULL值,这将变得笨拙。这rowversion就是方便的地方。

--check original rowversion value when updating row
UPDATE dbo.MyTest
SET myValue = @NewMyValue
WHERE
    myKey = 1
    AND (myValue = @OriginalMyValue
    OR (myValue IS NULL AND @OriginalMyValue IS NULL));
于 2015-08-27T02:49:52.787 回答
0

Timestamp 是 rowversion 的数据库同义词。你不需要了解任何奥秘,你不应该使用它。它已被弃用,将来将被删除。

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

于 2015-08-26T21:34:43.823 回答