51

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;
4

1 回答 1

62

我选择哪些列是否重要?

不,没关系。即使SELECT 1 FROM table WHERE ... FOR UPDATE使用,查询也会锁定所有满足 where 条件的行。

如果查询从连接中检索行,并且我们不想锁定连接中涉及的所有表中的行,而只锁定特定表中的行,SELECT ... FOR UPDATE OF list-of-tablenames则语法可能很有用:
http ://www.postgresql.org/docs /9.0/static/sql-select.html#SQL-FOR-UPDATE-SHARE


如果不将数据保存在某处,我无法在函数中进行选择,所以我保存到一个虚拟变量。这看起来很老套;这是做事的正确方式吗?

在 Pl/PgSql 中使用PERFORM命令丢弃查询结果:
http://www.postgresql.org/docs/9.2/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-SQL-NORESULT

而不是:

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

利用:

PERFORM 1 FROM my_table WHERE userid=v_1 LIMIT 1 FOR UPDATE;
于 2013-09-18T21:09:47.953 回答