这个sql更新是否保证是原子的?

时间:2016-06-27 17:00:37

标签: sql

我有以下sql:

UPDATE Customer SET Count=1 WHERE ID=1 AND Count=0
SELECT @@ROWCOUNT

我需要知道这是否保证是原子的。

如果2个用户同时尝试此操作,那么只有一个会成功并获得1的返回值吗?我是否需要使用交易或其他方式来保证这一点?

目标是获得一个独特的' Count'为客户。这个系统中的冲突几乎不会发生,因此如果用户必须再次(并且再次)查询以获得唯一的Count,我不关心性能。

编辑:

目标是在不需要时使用交易。此逻辑很少运行(每天最多100个),因此我希望尽可能简单。

2 个答案:

答案 0 :(得分:0)

它可能取决于您使用的sql server。但对大多数人来说,答案是肯定的。我猜你正在实施锁定。

答案 1 :(得分:0)

使用SQL SERVER(v 11.0.6020),这确实是我可以确定的原子操作。

我写了一些测试存储过程来尝试测试这个逻辑:

-- Attempt to update a Customer row with a new Count, returns 
-- The current count (used as customer order number) and a bit
-- which determines success or failure.  If @Success is 0, re-run
-- the query and try again.
CREATE PROCEDURE [dbo].[sp_TestUpdate]
(
  @Count INT OUTPUT,
  @Success BIT OUTPUT
) 
AS
BEGIN
   DECLARE @NextCount INT 

   SELECT @Count=Count FROM Customer WHERE ID=1
   SET @NextCount = @Count + 1
   UPDATE Customer SET Count=@NextCount WHERE ID=1 AND Count=@Count
   SET @Success=@@ROWCOUNT
END  

-- Loop (many times) trying to get a number and insert in into another
-- table.  Execute this loop concurrently in several different windows
-- using SMSS.
CREATE PROCEDURE [dbo].[sp_TestLoop]
AS
BEGIN
   DECLARE @Iterations INT
   DECLARE @Counter INT
   DECLARE @Count INT
   DECLARE @Success BIT
   SET @Iterations = 40000
   SET @Counter = 0
   WHILE (@Counter < @Iterations)
   BEGIN
      SET @Counter = @Counter + 1
      EXEC sp_TestUpdate @Count = @Count OUTPUT , @Success = @Success OUTPUT
      IF (@Success=1)
      BEGIN
          INSERT INTO TestImage (ImageNumber) VALUES (@Count)
      END
   END
END

此代码已运行,在TestImage表中创建唯一的顺序ImageNumber值。这证明上面的SQL更新调用确实是原子的。两个函数都没有保证更新已完成,但它们确保没有创建重复项,也没有跳过任何数字。