Re: race condition when checking uniqueness between two tables - Mailing list pgsql-general

From Tom Lane
Subject Re: race condition when checking uniqueness between two tables
Date
Msg-id 1954.1551394201@sss.pgh.pa.us
Whole thread Raw
In response to race condition when checking uniqueness between two tables  (Győző Papp <gyozo.papp@meltwater.com>)
List pgsql-general
=?UTF-8?B?R3nFkXrFkSBQYXBw?= <gyozo.papp@meltwater.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


pgsql-general by date:

Previous
From: Tom Lane
Date:
Subject: Re: Overloaded && operator from intarray module prevents index usage.
Next
From: Michael Lewis
Date:
Subject: Re: Overloaded && operator from intarray module prevents index usage.