在SQL中安全地更新计数(字段)

时间:2009-06-03 00:46:16

标签: sql concurrency

我想在userpost上实现类似标签的SO。我有一个名为tag_data的表,其中包含tagId,title,count。我有一个单独的表链接帖子和它可能使用的许多标签之间的关系。

继承问题,如何获得当前计数,将其增加或减少一个并将其保存为SAFELY。所以没有其他连接/线程会在我选择和更新之间更新它吗?

3 个答案:

答案 0 :(得分:13)

我假设你也想要新的计数,其他明智的做法是没有脑子,只需更新set count = count + 1.

如果UPDATE上的db support输出子句(例如SQL Server 2K5或2K8):

UPDATE table
   SET count = count + 1
   OUTPUT inserted.count
   WHERE id=@id;

否则:

begin transaction
update table 
    set counter=counter+1
    where id=@id;
select counter
    from table
    where id=@id;
commit;

答案 1 :(得分:0)

SET Count = Count + 1是IMHO最简单的解决方案..

更一般地说,能够获取数据,处理数据以及处理数据的概念要求在编写处理结果之前没有潜在的变化,如果您还需要可扩展的系统,通常不合理。

您当然可以这样做,并且在许多环境中都可以使用它。但是,在并发问题导致系统无法使用之前,这些方法将严重限制应用程序的可伸缩性和复杂性。

恕我直言,更好的方法是采取乐观的路线并检测/重试,如果在异常情况下你关心的事情确实发生了变化。

SELECT Count AS old ... FROM ...

..处理......

UPDATE ... SET Count = oldplus1 WHERE Count = old AND ...

除非UPDATE为您提供您期望的行数,否则您会假设数据已被修改并重试,直到成功为止。

答案 2 :(得分:-2)

伪代码:

begin transaction
A = select count from tag_data where tagId = TagId
update tag_data set count = A+1 where tagId = TagId
commit
end transaction

我强烈建议您创建一个名为increment_tag(TagId)的存储过程来执行上述操作:)