事务隔离级别和子查询

The*_*Dag 5 sql-server concurrency isolation-level

如果我们有一个带有子 SELECT 的 UPDATE,子查询是否可以在 READ COMMITTED 隔离下并发执行?

换句话说,以下是否存在竞争条件:

update list set [state] = 'active' 
where
    id = (select top 1 id from list where [state] = 'ready' order by id)
Run Code Online (Sandbox Code Playgroud)

换句话说,如果许多连接同时执行此 SQL,我们能否保证每次调用实际上更新一行(只要处于“就绪”状态的行存在)?

The*_*Dag 2

答案是肯定的,存在竞争条件,两个事务可能同时执行子查询,导致同一行随后被更新两次。

这可以通过将更新重写为来解决

update TEMP 
set [state] = 'active' 
from 
    (select top 1 * from list where [state] = 'ready' order by id) TEMP
Run Code Online (Sandbox Code Playgroud)

坦率地说,我不知道为什么会有所不同,但确实如此。SQL Server 现在将在执行子查询时获取更新锁(“意图更新”),以防止并发事务选择同一行。