确保只有一个 SQL 更新进行更改所需的最低隔离度是多少?



这里有一个带参数的SQL UPDATE命令。。。

UPDATE MyTable 
SET MyField = @newvalue, 
    @success = 1
WHERE 
    Id = @id 
    AND MyField = @oldvalue

许多客户端将同时使用相同的@id@oldvalue参数值运行此命令。我只想让其中一个成为"赢家",并将MyField设置为它自己的@newvalue,让它知道它赢了,因为@success输出参数将设置为1。

要做到这一点并保证只有一个客户会"获胜",最低隔离级别是多少?这一对账单需要交易吗?

我使用的是SQL Server 2008,但我希望有一个标准的SQL答案。

SQL Server UPDATE语句将始终在更新的读取阶段设置一个(U)(更新锁),然后升级为(X)(独占锁),用于将新值实际写入正在更新的行(或页/表),而不管您使用的是哪种事务隔离级别。

由于一个(U)锁与同一级别上的另一个(U)锁不兼容,如果一个进程已经有了(U)锁定,则没有其他连接可以同时启动UPDATE,并且必须等待。

同样:这是SQL Server的标准行为,无论您使用的是哪个事务隔离级别,对于所有这些隔离级别都是一样的。

我不知道这句话对其他RDBMS系统是否有效——很可能不是。任何ANSI SQL标准都不会处理这类事情——它们总是非常特定于供应商。

如果新值总是与旧值不同,则默认隔离级别READ COMMITTED就足够了。

然而,如果价值最终可能与旧价值相同,那么所有客户都会成功。一个接一个。并且每个都将具有@success = 1

SQL Server的行为已经介绍过了,但我将进一步讨论关于"标准SQL答案"的问题。

我不知道有任何RDBMS需要比READ COMMITTED更严格的隔离级别才能获得您所要求的行为,前提是(如前所述)新值与旧值不同。我认为,SQL标准中各种事务隔离级别的要求应该保证任何符合要求的数据库产品都能做到这一点。这并不总是由其他答案中描述的锁类型来强制执行,但大多数系统使用某种阻塞锁来提供这种保证。

最新更新