Имеется следующий короткий код на Python. В основе кода используется библиотека psycopg2. Весь код работает в одной транзакции.
Что делает код? Он должен просто создать функцию с именем update_change_time_column(). После создания, функция, естественно, существует одна на всю схему.
# Рекомендательная блокировка на момент создания функции
self.exec( "SELECT pg_advisory_lock(12345);" )
# Проверка что функция уже есть в БД
resultCursor = self.exec( """SELECT EXISTS (
SELECT 1
FROM information_schema.routines
WHERE routine_name = 'update_change_time_column'
AND routine_schema = current_schema()
);""" )
isFunctionExists = resultCursor.fetchone()[0]
# Если функции нет, она создается
if not isFunctionExists:
self.exec( """
CREATE OR REPLACE FUNCTION update_change_time_column()
RETURNS TRIGGER AS $$
BEGIN
IF current_setting('custom.disable_change_time_trigger', true) IS NOT NULL THEN
RETURN NEW;
END IF;
NEW.change_time = now();
RETURN NEW;
END;
$$ language 'plpgsql';
""" )
# Рекомендательная блокировка снимается
self.exec( "SELECT pg_advisory_unlock(12345);" )
Важно: внешняя система может запустить данный код в параллель. Примерно 10 одинаковых копий этого кода работает одновременно. Не спрашивайте почему, это не моя разработка.
И при работе иногда возникает ошибка:
Ошибка при выполнении SQL-запроса
CREATE OR REPLACE FUNCTION update_change_time_column()
RETURNS TRIGGER AS $$
BEGIN
IF current_setting('custom.disable_change_time_trigger', true) IS NOT NULL THEN
RETURN NEW;
END IF;
NEW.change_time = now();
RETURN NEW;
END;
ОШИБКА: повторяющееся значение ключа нарушает ограничение уникальности "pg_proc_proname_args_nsp_index"
DETAIL: Ключ "(proname, proargtypes, pronamespace)=(update_change_time_column, , 2200)" уже существует.
Вопрос: почему возникает такая ошибка?
Вроде как предприняты меры по блокировке на время создания функции. Функция создается только в случае, если ее нет. Все обернуто в транзакцию. Что еще надо учитывать чтобы ошибки не возникало?