PostrgreSQL пытается выполнить функцию plsh

#postgresql #deadlock

#postgresql #взаимоблокировка

Вопрос:

ПРИМЕЧАНИЕ: plsh это язык PostgreSQL, который выполняет команды командной оболочки.

Я пытаюсь вызвать plsh функцию изнутри plpgsql функции.

Во-первых, есть более масштабная plpgsql функция:

 CREATE OR REPLACE FUNCTION my_schema.big_function(my_arg character varying)
RETURNS text AS
$BODY$
BEGIN
    DROP TABLE IF EXISTS backend.table_B;
    CREATE TABLE backend.table_B AS
    --Create a table with a SELECT with some joins,
    --right now the resulting table is empty

    RAISE NOTICE 'table_B created';

    PERFORM my_schema.insert_from_shell(my_arg);

    RETURN 'Function Ended';
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
  

Тогда есть plsh функция:

 CREATE OR REPLACE FUNCTION my_schema.insert_from_shell(my_arg character varying)
RETURNS text AS
$BODY$
#!/bin/sh
PGPASSWORD=mypassword psql -d mydatabase -h myhost -p myport -U myuser -c "INSERT INTO myschema.table_A(mycolumn) VALUES('$1')"
$BODY$
LANGUAGE plsh VOLATILE
COST 100;
  

Когда я пытаюсь выполнить следующее:

 SELECT my_schema.big_function('test');
  

это никогда не заканчивается. С другой стороны, если я прокомментирую PERFORM строку из первой функции и вызову обе функции по отдельности, каждая из них завершится менее чем за секунду:

 SELECT my_schema.big_function('test');
SELECT my_schema.insert_from_shell('test');
  

Может быть проблема с выполнением plsh функций изнутри plpgsql функций, но я не уверен.

Я мог бы обойти это, вызывая обе функции по отдельности, используя скрипт вне базы данных, но я бы предпочел решить это изнутри базы данных и вызвать единственную функцию.

Любой указатель или помощь будут высоко оценены.

Комментарии:

1. Что вы получаете за SELECT pid, relation::regclass, mode, granted FROM pg_locks; ? Бьюсь об заклад, big_function выполняется внутри транзакции с операторами, которые блокируют table_a .

2. Я думаю, вы, возможно, на что-то натолкнулись. Копнув немного глубже, я нашел функцию триггера, связывающую table_a и table_b . Есть ли способ зафиксировать создание table_a промежуточной функции?

Ответ №1:

Предполагая, что триггер в транзакции big_function устанавливает конфликтующую блокировку table_a , как предложено в комментарии, вы могли бы рассмотреть следующее решение:

Сделайте триггер a CONSTRAINT TRIGGER (тогда это должен быть AFTER триггер) и объявите его как DEFERRABLE INITIALLY DEFERRED . Тогда он не будет выполняться правильно, когда запускающий оператор выполняет, но будет отложен до COMMIT в конце транзакции.

К тому времени insert_from_shell завершится и зафиксируется, поэтому взаимоблокировки не будет.

Комментарии:

1. Сейчас я уже ушел из офиса, но я попробую завтра и дам вам знать! Большое спасибо!