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-我查看了变更数据捕获,但那太过分了。一个简单的时间戳就足够了。我只需要知道哪些记录还需要同步。我不需要完整的历史记录。