Postgres SELECT ... FOR UPDATE in functions

时间:2013-09-18 18:23:55

标签: postgresql plpgsql postgresql-9.1 select-for-update

我有两个关于在Postgres函数中使用SELECT ... FOR UPDATE行级锁定的问题:

  • 我选择哪些列是否重要?他们与我需要锁定然后更新的数据有什么关系吗?

    SELECT * FROM table WHERE x=y FOR UPDATE;
    

    VS

    SELECT 1 FROM table WHERE x=y FOR UPDATE;
    
  • 我不能在没有保存数据的情况下在函数中进行选择,所以我保存为虚拟变量。这似乎是hacky;这是正确的做事方式吗?

这是我的功能:

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;

1 个答案:

答案 0 :(得分:38)

  

我选择哪些列是否重要?

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

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


  

我不能在某个函数中执行select而不在某处保存数据,所以我保存为一个虚拟变量。这似乎是hacky;这是正确的做事方式吗?

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