Sql server 此UPDATE语句中是否存在可能的争用条件?

Sql server 此UPDATE语句中是否存在可能的争用条件?,sql-server,timestamp,race-condition,rowversion,database-concurrency,Sql Server,Timestamp,Race Condition,Rowversion,Database Concurrency,我正在写一个同步器软件,它将把一个数据库中的所有更改同步到另一个数据库。为此,我在我的表T中添加了两列: alter table T add LastUpdate rowversion, LastSync binary(8) not null default 0 现在,我可以轻松选择自上次同步以来已更改的所有行: select * from T where LastUpdate > LastSync 但是,在执行同步之后,我应该使这两个字段相等。但是更新行也会更新时间戳,所以我必须这样

我正在写一个同步器软件,它将把一个数据库中的所有更改同步到另一个数据库。为此,我在我的表
T
中添加了两列:

alter table T add LastUpdate rowversion, LastSync binary(8) not null default 0
现在,我可以轻松选择自上次同步以来已更改的所有行:

select * from T where LastUpdate > LastSync
但是,在执行同步之后,我应该使这两个字段相等。但是更新行也会更新时间戳,所以我必须这样做:

update T set LastSync=@@DBTS+1 where ID=@syncedId

但我想知道——这会一直有效吗?如果我读取了
@@DBTS
的值,然后另一个用户在提交我的行之前设法在某处插入/更新一行,该怎么办?这是危险代码吗?如果是-如何使其更好?

如果在可序列化的
事务中运行此操作,则其他读/写操作将无法影响这些表

RepeateableRead
也可以完成这项工作…

将“LastSync”存储在与实际数据相同的表中可能根本不是一个好主意。 尝试将其存储在另一个没有rowversion的表中。这样就避免了“更新行也更新时间戳”的问题

您的同步器软件可以这样工作:

  • 从附加表中获取@LastSync值
  • “从T中选择@ThisSync=max(LastUpdate),其中LastUpdate>@LastSync”

  • “从T中选择*其中LastUpdate>@LastSync和LastUpdate表-是。”。但是
    @@DBTS
    的值呢?它没有存储在任何表中@Vilx如果您在同步期间使用独占表锁,那么如果另一个表中的事件使
    @@DBTS
    增加,则可能无关紧要。@Martin Smith-但是@DBTS对于整个数据库是全局的。为什么不要紧?如果我为
    LastSync
    字段获得一个(较旧)值,为
    LastUpdate
    字段获得一个较新的值,“我的同步将被中断。@Vilx好的,如果您更新表并且
    @@DBTS
    的值为10,那么另一个表将更新两行,使
    @@DBTS
    的值等于12,并且您最终将12存储在
    LastSync
    字段中,这是一个问题吗?”?下次来同步时,您仍在查找
    LastUpdate>LastSync
    @Martin Smith所在的行-问题是,情况正好相反
    LastUpdate
    获取
    LastSync
    之后的值。否则我就不需要在查询中首先使用
    +1
    ,这是个好主意。我会记住这一点,以防没有更好的办法。顺便问一下,您使用的是什么版本的SQL Server?“这是一种选择吗?”我想是马丁·史密斯-2008。不确定客户机有什么。@Martin Smith-我查看了变更数据捕获,但那太过分了。一个简单的时间戳就足够了。我只需要知道哪些记录还需要同步。我不需要完整的历史记录。