> На какие действия можно повесить триггер (Go)
Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы
Компании: Avito
Стек: Go
> Пример ответа
Короткий ответ
В PostgreSQL триггеры можно повесить на события INSERT, UPDATE, DELETE и TRUNCATE для таблиц, а также на события CREATE, ALTER, DROP и другие DDL-операции для схем и баз данных. В Go-разработке чаще всего используются триггеры на уровне БД (PostgreSQL, MySQL) для аудита, валидации, каскадных обновлений и синхронизации данных. Также существуют логические триггеры в приложении - через middleware или хуки в ORM, но это не относится к БД-триггерам.
Подробное объяснение
Триггеры в реляционных БД - это процедуры, которые автоматически выполняются при наступлении определённого события. В PostgreSQL триггеры бывают:
- DML-триггеры - на INSERT, UPDATE, DELETE, TRUNCATE. Могут срабатывать до или после операции, для каждой строки или для всей команды (statement-level).
- DDL-триггеры - на CREATE, ALTER, DROP, GRANT, REVOKE и другие события для таблиц, индексов, функций, схем. Срабатывают на уровне базы данных или схемы.
- Event triggers - глобальные, на уровне кластера, например, на событие
ddl_command_startилиddl_command_end.
В MySQL триггеры поддерживают только INSERT, UPDATE, DELETE, и только на уровне строк. В SQLite - INSERT, UPDATE, DELETE, но с ограничениями.
В Go-приложениях триггеры обычно реализуются на стороне БД через миграции (например, goose, golang-migrate). Альтернатива - прикладные хуки: в GORM есть BeforeSave, AfterCreate и т.п., но это не БД-триггеры, а часть ORM-логики.
На практике
Для senior-разработчика важно понимать trade-off между триггерами в БД и логикой в приложении. Триггеры гарантируют целостность данных на уровне БД, работают для любых клиентов (не только Go-сервисов), но усложняют отладку и тестирование. Прикладные хуки проще поддерживать, но они не защищают от прямых запросов к БД.
Типичные сценарии использования триггеров в Go-проектах:
- аудит изменений (лог кто и когда изменил запись);
- автоматическое обновление
updated_at; - каскадное обновление связанных таблиц;
- валидация данных, которую сложно выразить через CHECK-constraint;
- синхронизация с поисковым индексом или кэшем (через outbox-паттерн).
При проектировании стоит избегать тяжёлых вычислений в триггерах - они выполняются в транзакции и блокируют строки. Также нужно помнить про порядок срабатывания нескольких триггеров на одно событие - он определяется алфавитным порядком имён.
Пример кода
SQL-- Триггер на обновление updated_atCREATE OR REPLACE FUNCTION set_updated_at()RETURNS TRIGGER AS $$BEGINNEW.updated_at = NOW();RETURN NEW;END;$$ LANGUAGE plpgsql;CREATE TRIGGER trg_users_updated_atBEFORE UPDATE ON usersFOR EACH ROWEXECUTE FUNCTION set_updated_at();
GO// Миграция с использованием goose// 00001_create_trigger.sql-- +goose UpCREATE TRIGGER trg_orders_auditAFTER INSERT OR UPDATE OR DELETE ON ordersFOR EACH ROWEXECUTE FUNCTION log_order_change();-- +goose DownDROP TRIGGER IF EXISTS trg_orders_audit ON orders;
Как отвечать на собеседовании
Начни с чёткого перечисления типов триггеров и событий. Затем приведи пример из практики - лучше, если это будет реальный кейс: аудит, синхронизация, защита от некорректных данных. Покажи понимание различий между row-level и statement-level триггерами, а также между триггерами в БД и хуками в ORM. Если спросят про производительность - упомяни, что триггеры выполняются в транзакции, и это может быть узким местом. Хорошо, если ты сможешь обосновать выбор триггера вместо логики в Go: например, когда данные могут меняться из разных источников.
Что проверяет интервьюер
Интервьюер оценивает:
- знание синтаксиса и возможностей конкретной СУБД (PostgreSQL, MySQL);
- понимание, когда триггеры уместны, а когда - нет;
- умение проектировать миграции и поддерживать схему БД;
- осознание рисков: сложность отладки, влияние на производительность, скрытая логика;
- способность объяснить альтернативы (CHECK, FOREIGN KEY, прикладные хуки).
Типичные ошибки
- Путаница между триггерами в БД и хуками ORM - это разные механизмы.
- Утверждение, что триггеры работают в MySQL на уровне statement - это не так.
- Игнорирование порядка срабатывания триггеров и рекурсивных вызовов.
- Размещение тяжёлой бизнес-логики в триггере - это замедляет все операции с таблицей.
- Забывают про
TRUNCATE- на него тоже можно повесить триггер в PostgreSQL. - Не учитывают, что триггеры не видны в коде приложения - это усложняет онбординг и поддержку.
> Похожие задачи по Go
Влияют ли индексы на другие запросы кроме ускорения поиска
Как генерировать короткую ссылку в системе url shortener
Есть ли у TCP и UDP операция подтверждения доставки
Что происходит если памяти не хватает
> Похожие задачи по backend
Влияют ли индексы на другие запросы кроме ускорения поиска
Как генерировать короткую ссылку в системе url shortener
Есть ли у TCP и UDP операция подтверждения доставки
Что происходит если памяти не хватает
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью