Re: SELECT FOR UDPATE behavior inside joins

From: Adrian Klaver <adrian(dot)klaver(at)aklaver(dot)com>
To: "Khan, Tanzeel" <tzlkhan(at)amazon(dot)com>, "pgsql-general(at)lists(dot)postgresql(dot)org" <pgsql-general(at)lists(dot)postgresql(dot)org>
Subject: Re: SELECT FOR UDPATE behavior inside joins
Date: 2025-12-31 15:35:38
Message-ID: 3fbea48a-54e9-4af2-880d-35707cc56d72@aklaver.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-general

On 12/29/25 01:15, Khan, Tanzeel wrote:
> Hi,
>
> I am trying to understand the SELECT FOR UPDATE behavior when it is not
> returning rows back to client.
>
> postgres=> CREATE TABLE t (col1 INT, col2 INT);
> postgres=> INSERT INTO t VALUES (1, 1);
>
> S1: BEGIN; UPDATE t SET col2 = col2 + 1 WHERE col1 = 1;
> S2: BEGIN; WITH cte AS (SELECT * FROM t WHERE col1 = 1 FOR UPDATE)
> UPDATE t SET col2 = t.col2 + 1 FROM cte AS t_self_join WHERE (t.col2 =
> t_self_join.col2);
> S1: COMMIT;
> S2: zero rows updated
>
> Why does session 2 update zero rows ? Shouldn’t the SELECT FOR UPDATE
> and UPDATE read the new version of the row as per
> > If so, the second updater proceeds with its operation using the
> updated version of the row. In the case of SELECT FOR UPDATE and SELECT
> FOR SHARE, this means it is the updated version of the row that is
> locked and returned to the client.
> https://www.postgresql.org/docs/current/transaction-iso.html#XACT-READ-
> COMMITTED <https://www.postgresql.org/docs/current/transaction-
> iso.html#XACT-READ-COMMITTED>
>
> Does this mean the new version for row is only returned when the SELECT
> FOR SHARE is returning rows back to client ?

No I think you missed the sentence before the one you you show above:

"The search condition of the command (the WHERE clause) is re-evaluated
to see if the updated version of the row still matches the search
condition. If so, the second updater proceeds with its operation using
the updated version of the row."

So:

WHERE (t.col2 = t_self_join.col2)

The S1 UPDATE changed the value of col2 to something different then what
is is found by WITH cte AS (SELECT * FROM t WHERE col1 = 1 FOR UPDATE).

>
> ------
> Thanks,
> Tanzeel

--
Adrian Klaver
adrian(dot)klaver(at)aklaver(dot)com

In response to

Browse pgsql-general by date

  From Date Subject
Next Message Khan, Tanzeel 2026-01-01 08:40:40 Re: SELECT FOR UDPATE behavior inside joins
Previous Message Tom Lane 2025-12-31 15:33:12 Re: SELECT FOR UDPATE behavior inside joins