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

时间:2010-10-22 11:00:32

标签: 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

然而,在执行同步之后,我应该使两个字段相等。但是更新行也会更新时间戳,所以我必须这样做:

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

但我想知道 - 这总是有效吗?如果我读取@@DBTS的值然后另一个用户设法在我的行被提交之前在某处插入/更新一行,该怎么办?这是冒险的代码吗?如果是的话 - 它怎么能变得更好?

2 个答案:

答案 0 :(得分:4)

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

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

  • 从附加表中获取@LastSync值
  • “从T中选择@ThisSync = max(LastUpdate),其中LastUpdate> @LastSync”
  • “从T中选择*,其中LastUpdate> @LastSync和LastUpdate< = @ThisSync”是您的同步行
  • 将@ThisSync存储为附加表格中的新“LastSync”。

同步运行时修改的条目将具有比max()查询更高的rowversion值。它们将在下次调用同步器时进行同步。

答案 1 :(得分:-1)

如果你在Serializable事务中运行它,那么其他任何读/写都不会影响这些表。

RepeateableRead也可以做这个......

相关问题