Search code examples
postgresqllockingselect-for-update

How to understand FOR UPDATE OF my_table?


I use Spring Data Jpa to work with the Postgres database. When accessing the database, the following query is generated:

select
    user0_.user_id as user_id1_0_,
    user0_.birthday as birthday2_0_,
    user0_.username as username3_0_ 
from
    users user0_ 
where
    user0_.username=$1
limit $2
for update of user0_ skip locked

Examples on the Internet usually indicate that columns are specified after for update of, but a table is specified here in the query. What will be blocked in this case? The whole row?


Solution

  • While the FROM clause only includes a single table (users AS user0_ in the example), there is effectively no difference between FOR UPDATE OF user0_ and simply FOR UPDATE. But it makes a difference with multiple tables in the FROM clause.
    The manual explains in depth:

    If specific tables are named in a locking clause, then only rows coming from those tables are locked; any other tables used in the SELECT are simply read as usual. A locking clause without a table list affects all tables used in the statement. If a locking clause is applied to a view or sub-query, it affects all tables used in the view or sub-query. However, these clauses do not apply to WITH queries referenced by the primary query. If you want row locking to occur within a WITH query, specify a locking clause within the WITH query.

    And no, you cannot list columns there in Postgres. Only tables. Postgres locks selected rows with this clause. Not columns.