Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Postgres SELECT ... FOR UPDATE in functions

I have two questions about using SELECT … FOR UPDATE row-level locking in a Postgres function:

  • Does it matter which columns I select? Do they have any relation to what data I need to lock and then update?

    SELECT * FROM table WHERE x=y FOR UPDATE; 

    vs

    SELECT 1 FROM table WHERE x=y FOR UPDATE; 
  • I can't do a select in a function without saving the data somewhere, so I save to a dummy variable. This seems hacky; is it the right way to do things?

Here is my function:

CREATE OR REPLACE FUNCTION update_message(v_1 INTEGER, v_timestamp INTEGER, v_version INTEGER) RETURNS void AS $$ DECLARE     v_timestamp_conv TIMESTAMP;     dummy INTEGER; BEGIN     SELECT timestamp 'epoch' + v_timestamp * interval '1 second' INTO v_timestamp_conv;     SELECT 1 INTO dummy FROM my_table WHERE userid=v_1 LIMIT 1 FOR UPDATE;     UPDATE my_table SET (timestamp) = (v_timestamp_conv) WHERE userid=v_1 AND version < v_version; END; $$  LANGUAGE plpgsql; 
like image 263
Dan Taylor Avatar asked Sep 18 '13 18:09

Dan Taylor


People also ask

What is SELECT for update in PostgreSQL?

The select ... for update acquires a ROW SHARE LOCK on a table. This lock conflicts with the EXCLUSIVE lock needed for an update statement, and prevents any changes that could happen concurrently. All the locks will be released when the transaction ends.

How do I use update SELECT?

The SELECT FOR UPDATE statement is used to order transactions by controlling concurrent access to one or more rows of a table. It works by locking the rows returned by a selection query, such that other transactions trying to access those rows are forced to wait for the transaction that locked the rows to finish.

How do I modify a function in PostgreSQL?

To start the function editor, navigate to the desired function in the schema browser, select the 'Source Code' tab and click on the 'Edit In Function Editor' button. Alternatively, you can right-click on the function in the schema browser and select 'Edit In Function Editor'.


1 Answers

Does it matter which columns I select?

No, it doesn't matter. Even if SELECT 1 FROM table WHERE ... FOR UPDATE is used, the query locks all rows that meet where conditions.

If the query retrieves rows from a join, and we don't want to lock rows from all tables involved in the join, but only rows from specific tables, a SELECT ... FOR UPDATE OF list-of-tablenames syntax can be usefull:
http://www.postgresql.org/docs/9.0/static/sql-select.html#SQL-FOR-UPDATE-SHARE


I can't do a select in a function without saving the data somewhere, so I save to a dummy variable. This seems hacky; is it the right way to do things?

In Pl/PgSql use a PERFORM command to discard query result:
http://www.postgresql.org/docs/9.2/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-SQL-NORESULT

Instead of:

SELECT 1 INTO dummy FROM my_table WHERE userid=v_1 LIMIT 1 FOR UPDATE; 

use:

PERFORM 1 FROM my_table WHERE userid=v_1 LIMIT 1 FOR UPDATE; 
like image 82
krokodilko Avatar answered Sep 22 '22 16:09

krokodilko