简体   繁体   English

Postgresql函数,它锁定表,更新值并返回行

[英]Postgresql function which locks table, updates value and returns row

For my Hi/Lo implementation, I need a function which will acquire exclusive table lock, update value and select one row. 对于我的Hi / Lo实现,我需要一个函数来获取独占表锁,更新值并选择一行。 I came up with the following code: 我想出了以下代码:

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;

However, when invoking the function, it returns not a row, but one column with a content similar to "unnamed portal 3". 但是,在调用该函数时,它不返回行,而是返回一个内容类似于“未命名的门户3”的列。 I guess I should iterate over returned ref (but how)? 我想我应该迭代返回的ref(但是如何)?

Another approach that I could use is to use UPDATE RETURNING statement, but I'm not sure if race conditions can occur in this case. 我可以使用的另一种方法是使用UPDATE RETURNING语句,但我不确定在这种情况下是否会出现竞争条件。 Any help would be appreciated. 任何帮助,将不胜感激。 Thanks 谢谢

This seems far more simple to me: 这对我来说似乎更简单:

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;

I also usually define RETURNS TABLE (col1 varchar, col2 varchar...) instead of RETURNS setof record . 我通常也定义RETURNS TABLE (col1 varchar, col2 varchar...)而不是RETURNS setof record

You are using a cursor variable (which you did not declare, and missing some other PL/pgSQL required elements too) and you return that. 您正在使用cursor变量(您没有声明,并且缺少其他一些PL / pgSQL所需的元素)并且您返回该变量。 Cursor references are indeed called "portals" so that explains your output. 游标引用确实称为“门户”,因此可以解释您的输出。 A better approach is this: 更好的方法是:

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;

But do you really need an exclusive lock on the table? 但你真的需要在桌子上独家锁吗? There are much less invasive approaches to getting a consistent table snapshot. 获取一致的表快照的入侵方法要少得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM