Re: UPDATE grabs multiple rows when it seems like it should only grab one

Поиск
Список
Период
Сортировка
От David G. Johnston
Тема Re: UPDATE grabs multiple rows when it seems like it should only grab one
Дата
Msg-id CAKFQuwbmJcw0j=qjDjJaLA=97wB-J8fiz_e0-hObsN=s8J+nAw@mail.gmail.com
обсуждение исходный текст
Ответ на Re: UPDATE grabs multiple rows when it seems like it should only grab one  (Tom Lane <tgl@sss.pgh.pa.us>)
Ответы Re: UPDATE grabs multiple rows when it seems like it should only grab one  (Tom Lane <tgl@sss.pgh.pa.us>)
Список pgsql-bugs
On Fri, Apr 22, 2016 at 4:09 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

> Kevin Burke <burke@shyp.com> writes:
> > I'm trying to write a job queue that grabs one job at a time from the
> > queue. I expect that the following query should update a maximum of one
> row
> > in the table:
>
> > UPDATE queued_jobs
> > SET status=3D'in-progress',
> >         updated_at=3Dnow()
> > FROM (
> >         SELECT id AS inner_id
> >         FROM queued_jobs
> >         WHERE status=3D'queued'
> >                 AND name =3D $1
> >                 AND run_after <=3D now()
> >         LIMIT 1
> >         FOR UPDATE
> > ) find_job
> > WHERE queued_jobs.id =3D find_job.inner_id
> >         AND status=3D'queued'
>
> I think you're assuming that the sub-query will always select the same
> row, but it doesn't have to.


=E2=80=8BActually, I assumed that the uncorrelated subquery would only be r=
un a
single time...=E2=80=8B

=E2=80=8BThe documentation on update, to me, seems to support this interpre=
tation.

"""
When using FROM you should ensure that the join produces at most one output
row for each row to be modified. In other words, a target row shouldn't
join to more than one row from the other table(s)
"""=E2=80=8B

=E2=80=8BThe understanding of JOIN that I hold is to take two complete rela=
tions
and combine them on some predicate.  The from relation here, when complete,
only has one row and given it is effectively a self-join on the PK the
result of the join is guaranteed to be a single row.  I do not follow how
the sub-select is allowed to be evaluated multiple times.=E2=80=8B

LIMIT without an ORDER BY is ill-defined.
> Another problem is that once the outer UPDATE has changed the status
> of whichever row the sub-query selects initially, that row isn't
> a candidate to be returned by later subquery runs, so it'd certainly
> move on to another row.  (I'm assuming here that FOR UPDATE allows
> the sub-query to see the effects of the outer update immediately,
> which might be wrong; I lack the time to go check right now.)
>
> You might have better luck by putting the sub-query in a CTE, where
> it will be executed at most once.
>

=E2=80=8BSince I presume that is the desired semantics here=E2=80=8B

=E2=80=8Bthat seems like this is the best proper solution.  Though now I'm =
curious
what people did before CTEs were available...this problem isn't new.

David J.
=E2=80=8B

В списке pgsql-bugs по дате отправления:

Предыдущее
От: Tom Lane
Дата:
Сообщение: Re: UPDATE grabs multiple rows when it seems like it should only grab one
Следующее
От: Kevin Burke
Дата:
Сообщение: Re: UPDATE grabs multiple rows when it seems like it should only grab one