Триггерные функции, запуск до и после команды, аудит и скрытая цена
Триггер — код, который PostgreSQL автоматически запускает при INSERT,
UPDATE, DELETE или другом событии таблицы. Клиент не вызывает его напрямую,
поэтому триггер работает для всех способов записи.
Это полезно для локального правила или аудита, но скрытая работа легко делает систему непонятной. Сначала спрашивайте, не будет ли явная команда приложения проще.
Триггер состоит из двух объектов. Триггерная функция содержит код, а
CREATE TRIGGER связывает её с таблицей, событием и моментом запуска:
CREATE FUNCTION marketplace.set_updated_at()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
NEW.updated_at := clock_timestamp();
RETURN NEW;
END
$function$;
CREATE TRIGGER orders_set_updated_at
BEFORE UPDATE ON marketplace.orders
FOR EACH ROW EXECUTE FUNCTION marketplace.set_updated_at();NEW — новая версия изменяемой строки. Триггер запускается перед каждым
UPDATE, записывает текущее время и возвращает строку для продолжения операции.
BEFORE запускается до изменения. Построчный триггер может изменить NEW
или вернуть NULL, чтобы пропустить строку.AFTER запускается после завершённого изменения. Он подходит для записи
аудита; возвращаемое им значение строки игнорируется.INSTEAD OF выполняется вместо операции над представлением.FOR EACH ROW вызывает функцию для каждой строки. Обновление 100 000 строк
запустит её 100 000 раз.
Триггер уровня команды (FOR EACH STATEMENT) запускается один раз. Для
AFTER-триггера можно получить старый и новый набор изменённых строк через
переходные таблицы (transition tables):
CREATE TRIGGER orders_audit
AFTER UPDATE ON marketplace.orders
REFERENCING OLD TABLE AS old_rows NEW TABLE AS new_rows
FOR EACH STATEMENT EXECUTE FUNCTION marketplace.audit_order_changes();Функция может сравнить old_rows и new_rows одной операцией над набором,
вместо отдельного запроса на каждую строку. Для переходных таблиц действуют
ограничения по событию и моменту запуска, поэтому точный синтаксис сверяют с
документацией версии.
Стоит выбрать другое решение, если триггер:
Внешнее событие нельзя надёжно отправить в сеть «вместе» с фиксацией транзакции.
Обычно событие сначала записывают в таблицу исходящих сообщений в той же
транзакции. После COMMIT отдельный обработчик публикует его. Такой приём
называют транзакционной исходящей очередью (transactional outbox).
Системные каталоги pg_trigger и pg_proc показывают триггеры и функции.
pg_get_triggerdef() возвращает определение, а pg_trigger_depth() — текущую
глубину вложенных вызовов.
При медленной записи изучайте также SQL внутри функции. Не отключайте пользовательские триггеры в рабочей базе ради ускорения загрузки, пока не понятно, какие правила и аудит перестанут выполняться.
В лаборатории 17 вы сравните построчный триггер с триггером уровня команды и переходной таблицей, а затем проверите, что откат основной транзакции откатывает и аудит.
Подробнее: определение триггеров.
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.
Далее: Транзакции и блокировки