Re: race condition when checking uniqueness between two tables

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Győző Papp <gyozo(dot)papp(at)meltwater(dot)com>
Cc: pgsql-general(at)postgresql(dot)org
Subject: Re: race condition when checking uniqueness between two tables
Date: 2019-02-28 22:50:01
Message-ID: 1954.1551394201@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

=?UTF-8?B?R3nFkXrFkSBQYXBw?= <gyozo(dot)papp(at)meltwater(dot)com> writes:
> A periodic task moves rows form `available_jobs` to `assigned_jobs`
> the jobs that has been assigned:

> WITH jobs_to_assign AS (
> DELETE FROM available_jobs
> USING v_assignable_jobs
> WHERE available_jobs.id = v_assignable_jobs.id
> RETURNING available_jobs.*
> )
> INSERT
> INTO assigned_jobs(id, url)
> SELECT id, url
> FROM jobs_to_assign
> RETURNING *;

> And a similar one that “unassigns” failed assigned jobs, that is,
> pushes back rows from `assigned_jobs` to `available_jobs`. And it
> sometimes fails with:
> ERROR: duplicate key value violates unique constraint "jobs_pkey"
> DETAIL: Key (id)=(1fd0626c-f953-3278-82a1-8e4320d28914) already
> exists.

What is v_assignable_jobs?

If, as I suspect, it's a view involving these same tables, then
likely your issue is that you aren't reading that view with suitable
locking, so that sometimes it will return stale rows that describe
no-longer-assignable jobs.

DELETE doesn't have an option to apply FOR UPDATE to USING tables,
AFAIR, but maybe you could fix it along this line:

WITH jobs_to_assign AS (
SELECT id FROM v_assignable_jobs
FOR UPDATE
), deleted_jobs AS (
DELETE FROM available_jobs
USING jobs_to_assign
WHERE available_jobs.id = jobs_to_assign.id
RETURNING available_jobs.*
)
INSERT ... about as before, but use deleted_jobs ...

> * Each transaction is in READ_COMMITTED.

Another line of thought is to use SERIALIZABLE mode and just retry
the inevitable serialization failures. However, if there are a lot
of concurrent processes doing this, you'd probably get so many
serialization failures that it'd be quite inefficient.

regards, tom lane

In response to

Browse pgsql-general by date

  From Date Subject
Next Message Michael Lewis 2019-02-28 22:53:02 Re: Overloaded && operator from intarray module prevents index usage.
Previous Message Tom Lane 2019-02-28 22:34:20 Re: Overloaded && operator from intarray module prevents index usage.