Postgres SELECT ... FOR UPDATE 函数

Posted

技术标签:

【中文标题】Postgres SELECT ... FOR UPDATE 函数【英文标题】:Postgres SELECT ... FOR UPDATE in functions 【发布时间】:2013-09-23 15:31:26 【问题描述】:

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

【问题讨论】:

如果这真的是你的全部功能,那么select .. for update 没有任何用途。 UPDATE 也将锁定该行。如果你真的没有在 SELECTUPDATE 之间做任何工作,你可以完全省略 SELECT 并让你的函数更快。 【参考方案1】:

我选择哪些列重要吗?

不,没关系。即使使用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;

【讨论】:

以上是关于Postgres SELECT ... FOR UPDATE 函数的主要内容,如果未能解决你的问题,请参考以下文章

Postgres:SELECT FOR UPDATE 在锁定释放后看不到新行

塔的国家/地区WebHelpers选项u for u select()(不完整)

postgres 查询返回记录集的函数

django select_for_update 获取关系锁

Postgres SequelizeDatabaseError:返回或接近返回的语法错误

使用 Postgres 函数作为 ActiveRecord 模型