初始化我的进程时,它会运行下面的PL / pgSQL语句,创建两个函数.但是,每次我作为端到端测试的一部分同时创建多个进程时,此语句的并行执行会导致元组同时更新的错误,我似乎无法解决这个问题.任何帮助将非常感激.
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()
最佳答案 如
here所述,postgres目前不允许您同时使用CREATE FUNCTION:
It’d be necessary to add
some kind of locking scheme if you want to avoid “tuple concurrently
updated” errors. This is not really any different from the situation
where two transactions both want to update the same row in a user table:
unless the application takes extra steps to serialize the updates, you’re
going to get “tuple concurrently updated” errors.We do have such locking for DDL on tables/indexes, but the theory in the
past has been that it’s not worth the trouble for objects represented by
single catalog rows, such as functions or roles.
对此的解决方案是确保没有两个事务同时尝试执行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;
这需要一个事务级别的独占顾问锁,这样就不能同时运行两个并发事务来创建该函数.在事务结束时,锁会自动释放.