代码之家  ›  专栏  ›  技术社区  ›  Ryan O'Neill

如果在单个update语句中执行,SQL中的操作是否保证是原子的?

  •  1
  • Ryan O'Neill  · 技术社区  · 15 年前

    我试图用下面的代码消除显式锁定表的需要,但是从我得到的报告来看,行中的参数和值可能存在争用情况。

        Declare @NextNumber Int;
    
    Update
        MyParameterTable
    Set
        NextNumber = NextNumber + 1,
        @NextNumber = NextNumber + 1
    
    Select @NextNumber As NextNumber;
    

    希望您能看到它只是增加一个整数并返回结果。我的印象是,以这种方式格式化的update语句将处理必要的锁,但正如我所说的,可能是在update锁之外指定了参数。

    2 回复  |  直到 15 年前
        1
  •  3
  •   Matt Whitfield    15 年前

    这将很好地锁定,但您可以在一个由三部分组成的平等声明中实现:

    Declare @NextNumber Int;
    
    Update
        MyParameterTable
    Set
        @NextNumber = NextNumber = NextNumber + 1
    
    Select @NextNumber As NextNumber;
    
        2
  •  1
  •   momo    15 年前

    我的理解是,您的查询不会有竞争条件或并发问题。

    不过,我不喜欢使用这种语法,因为它可能会出现以下情况下的问题:

    Update MyParameterTable
    Set
       @NextNumber = NextNumber = NextNumber + 1,
       @NextNumber = @NextNumber + 1
    

    虽然我意识到你可能永远都不想这样做,但它以奇怪的方式断裂(第一行的处理方式与其他行不同)让我害怕相信它。在SQL 2000的某个特定SP中,这种语法也存在一些真正的错误。

    如果您想确保行被正确锁定,并且不会发生争用情况,那么下面是一个测试它的好方法。在SSMS/QA中打开多个查询窗口,并在每个窗口中执行以下操作:

    WAITFOR TIME '11:00:00' -- use a time in the near future
    EXEC dbo.YourProcedureName
    

    这将使您在不同会话中提交的所有批处理基本上在同一时刻运行,这是很难用任何其他方式模拟的。你很快就会得到一个关于是否会发生竞争状况的明确指标。

    我推荐一些文章供你进一步阅读。它们与这个问题无关,但绝对相关(在插入和更新中处理竞争条件):