Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transaction isolation levels and subqueries

if we have an UPDATE with a sub-SELECT, can the subquery execute concurrently or not under READ COMMITTED isolation?

In other words, is there a race condition present in the following:

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

In yet other words, if many connections are simulataneously executing this SQL, can we guarantee that one row is in fact updated per invocation (so long as rows in 'ready' state exist)?

like image 956
The Dag Avatar asked Nov 01 '22 00:11

The Dag


1 Answers

The answer is yes, there is a race condition and two transactions may execute the subquery concurrently, leading to the same row being subsequently updated twice.

This can be fixed by rewriting the update as

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

I frankly don't know why this should be different, but it is. SQL Server will now take update locks ("intent to update") when executing the subquery, preventing concurrent transactions from picking the same row.

like image 83
The Dag Avatar answered Nov 10 '22 03:11

The Dag