Для чего нужны правила PostgreSQL? - PullRequest
35 голосов
/ 05 мая 2011

Вопрос

Я часто вижу, что в правилах следует избегать и вместо них использовать триггеры . Я вижу опасность в системе правил, но, безусловно, существуют правильные способы использования правил, верно? Что они?

Я спрашиваю это из общего интереса; Я не очень опытен с базами данных.

Пример возможного использования

Например, в прошлом мне нужно было заблокировать определенные данные, поэтому я сделал что-то вроде этого:

CREATE OR REPLACE RULE protect_data AS
  ON UPDATE TO exampletable             -- another similar rule for DELETE
  WHERE OLD.type = 'protected'
  DO INSTEAD NOTHING;

Тогда, если я хочу редактировать защищенные данные:

START TRANSACTION;
  ALTER TABLE exampletable DISABLE RULE protect_data;
  -- edit data as I like
  ALTER TABLE exampletable ENABLE RULE protect_data;
COMMIT;

Я согласен, что это хакерство, но я не смог изменить приложения, обращающиеся к базе данных в этом случае (или даже выдать ошибки). Так что бонусных баллов за нахождение причины, по которой это опасное / недопустимое использование системы правил , но не , почему это плохой дизайн .

Ответы [ 4 ]

17 голосов
/ 05 мая 2011

Одним из вариантов использования ПРАВИЛ являются обновляемые представления (хотя это изменение в 9.1, поскольку в этой версии вводятся триггеры INSTEAD OF для представлений)

Еще одно хорошее объяснение можно найти в руководстве:

Для вещей, которые могут быть реализованы обоими, что лучше всего зависит от использования базы данных. Триггер срабатывает для любой затронутой строки один раз. Правило управляет запросом или генерирует дополнительный запрос. Таким образом, если в одной инструкции затрагивается много строк, правило, выдающее одну дополнительную команду, скорее всего будет быстрее, чем триггер, который вызывается для каждой отдельной строки и должен выполнять свои операции много раз. Тем не менее, подход триггера концептуально намного проще, чем подход правил, и новичкам легче понять все правильно.

(взято из: http://www.postgresql.org/docs/current/static/rules-triggers.html)

12 голосов
/ 05 мая 2011

Некоторые проблемы с правилами показаны здесь: http://www.depesz.com/index.php/2010/06/15/to-rule-or-not-to-rule-that-is-the-question/ (например, если в запрос включен random (), он может быть выполнен дважды и вернуть разные значения).

Самый большой недостаток правил заключается в том, что люди не понимают их.

Например, можно подумать, что имея правило:

CREATE OR REPLACE RULE protect_data AS
  ON UPDATE TO exampletable             -- another similar rule for DELETE
  WHERE OLD.type = 'protected'
  DO INSTEAD NOTHING;

Будет означать, что если я выдам:

update exampletable set whatever = whatever + 1 where type = 'protected'

Ни один запрос не будет выполнен. Что не соответствует действительности. Запрос будет выполняться, но он будет выполняться в измененной версии - с добавленным условием.

Более того - правила нарушают очень полезную вещь, то есть возвращаемое предложение:

$ update exampletable set whatever = whatever + 1 where type = 'normal' returning *;
ERROR:  cannot perform UPDATE RETURNING on relation "exampletable"
HINT:  You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause.

Чтобы обернуть это - если вы действительно, действительно, положительно должны использовать доступные для записи представления, и вы используете pre 9.1 PostgreSQL - у вас может есть веская причина для использования правил.

Во всех других случаях - вы, скорее всего, стреляете себе в ногу, даже если вы не сразу это видите.

9 голосов
/ 08 мая 2011

У меня было несколько горьких опытов с правилами при работе с энергозависимыми функциями (если память не изменяет, некоторые из них в блоге depesz освещаются).

Я также нарушил ссылочную целостность при их использовании из-за времени срабатывания триггеров fkey:

CREATE OR REPLACE RULE protected_example AS
  ON DELETE TO example
  WHERE OLD.protected
  DO INSTEAD NOTHING;

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

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

Практический случай использования, где я все еще использую правила, - это когда BEFORE триггер, который предварительно манипулирует данными (стандарт SQL говорит, что это не разрешено, но Postgres с радостью выполнит обязательство), может привести к предварительной манипуляции с затронутыми строками и изменяя таким образом их ctid (то есть он обновляется дважды или не удаляется, потому что обновление делает недействительным удаление).

Это приводит к тому, что Postgres возвращает неверное количество затронутых строк, что не составляет особого труда, пока вы не проконтролируете это число перед выполнением последующих операторов.

В этом случае я обнаружил, что использование стратегически размещенного правила или двух может позволить превентивно выполнить ошибочные операторы, в результате чего Postgres вернет правильное количество затронутых строк.

5 голосов
/ 05 мая 2011

Как насчет этого: у вас есть таблица, которую нужно изменить в представление. Для поддержки устаревших приложений, которые вставляют в указанную таблицу, создается правило, которое сопоставляет «вставки» с новым представлением с базовой таблицей (таблицами).

...