初始化我的进程时,它运行下面的PL / pgSQL语句,创建两个函数。但是,每当我作为端到端测试的一部分同时创建多个进程时,此语句的并行执行会导致tuple concurrently updated
错误,我似乎无法解决这个问题。任何帮助将不胜感激。
CREATE OR REPLACE FUNCTION
count_rows(schema text, tablename text) returns integer
AS
$body$
DECLARE
result integer;
query varchar;
BEGIN
query := 'SELECT count(1) FROM "' || schema || '"."' || tablename || '"';
execute query into result;
return result;
END;
$body$
LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION
delete_if_empty(schema text, tablename text) RETURNS INTEGER
AS
$$
DECLARE
result integer;
query varchar;
BEGIN
query := 'SELECT COUNT(*) FROM "' || schema || '"."' || tablename || '"';
execute query into result;
IF result = 0 THEN
EXECUTE 'DROP TABLE "' || schema || '"."' || tablename || '" CASCADE;';
EXECUTE 'NOTIFY "' || schema || '", ''DESTROY_TABLE:' || tablename || ''';';
RETURN 1;
END IF;
RETURN 0;
END;
$$
LANGUAGE plpgsql;
SELECT version()
答案 0 :(得分:2)
正如here所述,postgres目前不允许同时使用CREATE FUNCTION
:
有必要添加 如果你想同时避免"元组,那么某种锁定方案 更新"错误。这与情况没有任何不同 其中两个事务都想要更新用户表中的同一行: 除非应用程序采取额外步骤来序列化更新,否则您就是其中之一 得到"元组同时更新"错误。
我们对表/索引上的DDL有这样的锁定,但是理论在 过去一直认为它不值得为它所代表的对象带来麻烦 单个目录行,例如函数或角色。
解决方案是确保没有两个交易同时尝试CREATE FUNCTION
。
您可以使用posgres 顾问锁。
可在此处找到有关咨询锁的详细介绍:https://vladmihalcea.com/how-do-postgresql-advisory-locks-work/
例如,您可以使用:
BEGIN; -- start of transaction
SELECT pg_advisory_xact_lock(2142616474639426746); -- random 64-bit signed ('bigint') lock number
CREATE OR REPLACE FUNCTION myfunction ...
COMMIT;
这需要一个事务级别的独占顾问锁,这样就不能同时运行两个并发事务来创建该函数。在交易结束时,锁定会自动释放。