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

时间:2010-02-05 10:23:49

标签: sql-server locking

我正在尝试删除使用以下代码显式锁定表的必要性,但是从报告我已经得到它可能是该行中的参数和值可能遇到竞争条件。

    Declare @NextNumber Int;

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

Select @NextNumber As NextNumber;

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

任何人都可以对此提出一些看法并建议替代方案吗?

此致

赖安

2 个答案:

答案 0 :(得分:3)

这将很好地锁定,但你可以用一个由三部分组成的平等陈述来完成:

Declare @NextNumber Int;

Update
    MyParameterTable
Set
    @NextNumber = NextNumber = NextNumber + 1

Select @NextNumber As NextNumber;

答案 1 :(得分:1)

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

我也认为@Variable = Column = / Expression /只是与您最初发布的完全相同的查询之外的语法糖。运行跟踪并检查获取和释放的锁将最终证明这一点。

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

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

这将使您在不同会话中提交的所有批次在基本完全相同的时刻运行,这是很难以任何其他方式模拟的。您很快就可以明确指出是否会出现竞争条件。

我推荐一些文章供你进一步阅读。他们不是关于这个问题,但肯定是相关的(处理插入和更新中的竞争条件):