【问题标题】:Postgresql function which locks table, updates value and returns rowPostgresql 函数,用于锁定表、更新值并返回行
【发布时间】:2016-08-29 23:31:47
【问题描述】:

对于我的 Hi/Lo 实现,我需要一个函数来获取独占表锁、更新值并选择一行。我想出了以下代码:

CREATE OR REPLACE FUNCTION bb_next_hi(tbl varchar(35))  
RETURNS setof record AS
$$ 
    LOCK TABLE hilo IN ACCESS EXCLUSIVE MODE;
    OPEN ref FOR SELECT hi as "Hi", lo as "Lo", "table" as "Table" FROM hilo WHERE "table" = $1;
    UPDATE hilo SET hi = hi + 1 WHERE "table" = $1
    RETURN ref;

$$ LANGUAGE plpgsql;

但是,在调用该函数时,它返回的不是一行,而是一列,其内容类似于“未命名的门户 3”。我想我应该迭代返回的 ref(但是如何)?

我可以使用的另一种方法是使用 UPDATE RETURNING 语句,但我不确定在这种情况下是否会出现竞争条件。任何帮助,将不胜感激。谢谢

【问题讨论】:

  • 如果只想锁定一行,为什么还要锁定整个表?
  • 我想也没有其他方法可以锁定读者。也许我错了,误解了一些东西,如果是这样的话,我会很高兴的:)

标签: postgresql


【解决方案1】:

这对我来说似乎要简单得多:

CREATE OR REPLACE FUNCTION bb_next_hi(tbl varchar(35))  
RETURNS setof record AS
$$ 
BEGIN
    LOCK TABLE hilo IN ACCESS EXCLUSIVE MODE;
    RETURN QUERY UPDATE hilo SET hi = hi + 1 WHERE "table" = $1
        RETURNING hi as "Hi", lo as "Lo", "table" as "Table";
END;
$$ LANGUAGE plpgsql;

我通常也定义RETURNS TABLE (col1 varchar, col2 varchar...) 而不是RETURNS setof record

【讨论】:

  • 这将返回“hi”的更新值,这与 OP 试图获取的值不同。
  • 确实如此,我没想到。不过,在 +=1 的情况下,这应该不是什么大问题。
【解决方案2】:

您正在使用 cursor 变量(您没有声明,并且还缺少一些其他 PL/pgSQL 必需的元素)并且您将其返回。光标引用确实被称为“门户”,以便解释您的输出。更好的方法是:

CREATE OR REPLACE FUNCTION bb_next_hi(tbl varchar(35))  
RETURNS TABLE ("Hi" int, "Lo" int, "Table" varchar(35)) AS $$
BEGIN
    LOCK TABLE hilo IN ACCESS EXCLUSIVE MODE;
    RETURN QUERY SELECT hi, lo, $1 FROM hilo WHERE "table" = $1;
    UPDATE hilo SET hi = hi + 1 WHERE "table" = $1;
    RETURN;
END;
$$ LANGUAGE plpgsql STRICT;

但是你真的需要一个排他锁吗?获得一致的表快照的侵入性要小得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-20
    • 2014-02-27
    • 2012-06-23
    • 1970-01-01
    • 2013-03-24
    • 1970-01-01
    • 2014-05-28
    相关资源
    最近更新 更多