TGViewer
Postgres Professional Postgres Professional @postgres_pro · 3.55K subscribers
Post #222 861
Как это работает: внешние ключи

Наверное многие уже знают правильный ответ. В конце концов, указанные команды несложно повторить и увидеть, что единственная команда, которая завершится ошибкой это DELETE:
DELETE FROM t;
ERROR: permission denied for table t
CONTEXT: SQL statement "SELECT 1 FROM ONLY "public"."t" x WHERE "id" OPERATOR(pg_catalog.=) $1 FOR KEY SHARE OF x"

Но как удаление только что добавленной строки может завершиться ошибкой? Почему у суперпользователя не хватает прав на таблицу t? И откуда взялась команда SELECT из контекста?

Все дело в ограничении внешнего ключа в таблице t: столбец parent_id ссылается на id этой же таблицы. Для реализации внешних ключей в PostgreSQL используются табличные триггеры. Их называют системными. Это триггеры на языке C, они создаются автоматически, команды psql их не показывают. Но их можно найти в системном каталоге pg_trigger, например в таблице t их сейчас 4. При удалении сработал триггер на DELETE. В триггере проверялось, что на удаляемую строку другие строки не ссылаются.

Так вот оказывается, что системные триггеры выполняются с правами владельца таблицы, а не с правами вызывающего команду DELETE. После выполнения REVOKE, прав на таблицу у app_owner нет. Поэтому любые пользователи будут получать подобные ошибки. Но если права вернуть, то всё заработает:
GRANT ALL ON t TO app_owner;
DELETE FROM t WHERE id = 1;
DELETE 1

Подобное поведение будет неожиданным для пришедших из других СУБД, где забирать у владельцев права на объекты вполне допустимо.

Но неожиданности в реализации системных триггеров на этом не заканчиваются. В недавней статье Broken foreign keys: how can that happen in PostgreSQL? Лауренц Альбе дает хорошее введение в системные триггеры и рассказывает как сломать ограничение внешнего ключа "законными" действиями.

Общий вывод: чтобы не нарушить согласованность данных, нужно учитывать работу системных триггеров. Это особенно важно при разработке собственных табличных триггеров.
  • 👍 10
  • 🔥 4
  • 🤔 3
  • ❤ 1
More from @postgres_pro
  1. Oct 12, 2026🐘 Приходите 15 октября на бесплатный вебинар по Postgres Pro AXE 2.0 — покажем, как ускор…
  2. Oct 10, 2026💛 Чтобы 1С на Postgres работала быстро, мало установить СУБД. Сегодня на INFOSTART TECH E…
  3. Oct 9, 2026Postgres Pro Enterprise для 1С: что умеет, как упрощает работу бизнеса и жизнь DBA, какие…
  4. Oct 8, 2026🤝 Postgres Professional и «ИнфоСофт» подписали меморандум о партнерстве на конференции IN…
  5. Oct 8, 2026🐉 Сегодня на INFOSTART TECH EVENT 2026 Алексей Викулин, руководитель по развитию бизнеса…
  6. Oct 7, 2026🐘 Вышла новая версия PPEM с Healthcheck Advisor. Модуль проверяет состояние экземпляров С…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →