PostgreSQL中函数中的FOR UPDATE语句意味着什么?

69

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

  • 我选择哪些列是否重要?它们与我需要锁定和更新的数据有何关系?

    SELECT * FROM table WHERE x=y FOR UPDATE;
    

    对峙

    SELECT 1 FROM table WHERE x=y FOR UPDATE;
    
  • 在函数中,如果我不保存数据就无法进行选择操作,所以我将其保存到虚拟变量中。这似乎很不规范,这是正确的做法吗?

这是我的函数:

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;

11
如果这确实是您的完整功能,那么select .. for update没有任何作用。 UPDATE同样可以锁定行。如果您在SELECTUPDATE之间真的没有做任何工作,可以完全省略SELECT并使您的函数更快。 - user330315
1个回答

88

选择哪些列无关紧要吗?

不会,即使使用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


我不能在函数中执行选择操作而不将数据保存到某个地方,所以我保存到一个虚拟变量中。这似乎很奇怪,这是正确的做法吗?

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接