I was wondering what happens when two transactions execute a SELECT ... FOR UPDATE
query in parallel. The background is that I want to implement a job queue using SELECT ... FOR UPDATE
with SKIP LOCKED
, as shown here: https://vladmihalcea.com/database-job-queue-skip-locked/. But in this article the queries are quite trivial.
An example with two transactions T1 and T2 (transaction isolation level is set to READ_COMMITTED
):
SELECT ... FOR UPDATE
, searching for NEW rows, which requires some time.SELECT ... FOR UPDATE
with same WHERE clause and parameters as T1, which also takes some time.Some questions:
SKIP LOCKED
, skip the marked rows? Will T2 re-evaluate it's result set after the changes made by T1?Each transaction locks the rows as it finds them, so locking is not atomic. It could happen that T1 locks a couple of rows and T2 locks some other rows.
Since each transaction locks rows immediately when it finds them, this cannot happen. Either a row is locked, in which case it is skipped, or it is not locked, in which case it is locked.
If T1 commits before T2 is done scanning the table, T2 will happily lock all rows that were already processed by T1.
Yes, that will work. T2 will fetch the most current version of each row before it checks the condition and locks the row.