Для чего хороши правила PostgreSQL?

вопрос

Я часто вижу, что он заявил, что следует избегать правил и использовать триггеры вместо. Я могу видеть опасность в системе правил, но, конечно, есть действительное использование правил, не так ли? Каковы они?

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

пример того, что может быть допустимым использовать

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

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 ответов


одним из вариантов использования правил являются обновляемые представления (хотя это изменяется в 9.1, поскольку эта версия вводит вместо триггеров для представлений)

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

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

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


некоторые проблемы с правилами показаны здесь: 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-you может есть веская причина использовать правила.

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


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

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

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

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

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

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

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

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


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