Триггеры базы данных

Раньше я никогда не был поклонником использования триггеров для таблиц базы данных. Для меня они всегда представляли некую «магию», которая должна была произойти на стороне базы данных, вдали от контроля моего кода приложения. Я также хотел ограничить объем работы, которую должна была выполнять БД, поскольку это обычно общий ресурс, и я всегда предполагал, что триггеры могут быть дорогими в сценариях с высокой нагрузкой.

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

Каковы общие мнения о триггерах? Любите их? Ненавижу их? Думаете, они служат определенной цели в некоторых сценариях? Считаете ли вы, что необходимость обойти триггер означает, что вы «делаете это неправильно»?


person Jesse Taber    schedule 18.08.2008    source источник


Ответы (12)


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

Том Кайт, вице-президент Oracle, указал, что он предпочел бы удалить триггеры как функцию базы данных Oracle из-за их частой роли в возникновении ошибок. Он знает, что это всего лишь сон, и триггеры здесь, чтобы остаться, но если бы он мог, он бы удалил триггеры из Oracle, он бы это сделал (вместе с предложением WHEN OTHERS и автономными транзакциями).

Можно ли правильно использовать триггеры? Абсолютно.

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

person Brian    schedule 18.08.2008

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

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

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

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

Что касается сокращения объема работы: базы данных потрясающе эффективны, когда им не приходится иметь дело с внешним миром; вы будете действительно удивлены, насколько даже переключение процессов вредит производительности. Это еще один положительный момент хранимых процедур: вместо дюжины обращений к базе данных (и всех связанных циклических обращений) есть один.

Сгруппировать данные в одной сохраненной процедуре - это нормально, но что произойдет, если что-то пойдет не так? Допустим, у вас есть 5 шагов, и первый шаг не удался, что происходит с другими шагами? Вам нужно добавить туда целую кучу логики, чтобы учесть эту ситуацию. Как только вы начнете это делать, вы потеряете все преимущества хранимой процедуры в этом сценарии.

Бизнес-логика должна куда-то уйти, и в структуру базы данных встроено множество подразумеваемых доменных правил - отношения, ограничения и т. Д. - это попытка кодифицировать бизнес-правила, говоря, например, что у пользователя может быть только один пароль. Учитывая, что вы начали переносить бизнес-правила на сервер базы данных, имея эти отношения и т. Д., Где вы проводите черту? Когда база данных откажется от ответственности за целостность данных и начнет доверять вызывающим приложениям и пользователям базы данных, чтобы все исправить? Сохраненные процедуры с этими встроенными в них правилами могут передать большую политическую власть в руки администраторов баз данных. Все сводится к тому, сколько уровней будет существовать в вашей n-уровневой архитектуре; если есть уровень представления, бизнеса и данных, где разделение между бизнесом и данными? Какие преимущества добавляет бизнес-уровень? Будете ли вы запускать бизнес-уровень на сервере базы данных как хранимые процедуры?

Да, я думаю, что необходимость обходить триггер означает, что вы «делаете это неправильно»; в этом случае триггер не для вас.

введите описание изображения здесь

person Josh    schedule 18.08.2008

Я работаю с веб-приложениями и приложениями winforms на C #, и я НЕНАВИЖУ триггеры. Я никогда не сталкивался с ситуацией, когда я мог бы оправдать использование триггера переносом этой логики на бизнес-уровень приложения и репликацией там логики триггера.

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

Некоторые причины, по которым мне не нравятся триггеры:

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

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

person lomaxx    schedule 18.08.2008
comment
Я использую триггеры в условных выражениях вставки / обновления / удаления для увеличения / уменьшения счетчиков в таблице. Прямо сейчас это единственный раз, когда я им пользуюсь. Эти триггеры в порядке? - person ; 20.10.2010

«Никогда не создавайте триггер для проверки ограничений целостности, пересекающих строки в таблице» - я не могу согласиться. Вопрос помечен как «SQL Server», а предложения CHECK constraints в SQL Server не могут содержать подзапрос; Хуже того, реализация, похоже, имеет «жестко закодированное» предположение, что CHECK будет включать только одну строку, поэтому использование функции ненадежно. Итак, если мне нужно ограничение, которое на законных основаниях включает более одной строки - и хорошим примером здесь является упорядоченный первичный ключ в классической временной таблице `` допустимое время '', где мне нужно предотвратить перекрытие периодов для одного и того же объекта - как можно Я делаю это без триггера? Помните, что это первичный ключ, что-то, что нужно для обеспечения целостности данных, поэтому о его применении где-либо, кроме СУБД, не может быть и речи. Пока ограничения CHECK не получат подзапросы, я не вижу альтернативы использованию триггеров для определенных видов ограничений целостности.

person onedaywhen    schedule 14.10.2008

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

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

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

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

Общее правило, которое я использую для триггеров, - делать их легкими, быстрыми, простыми и максимально неинвазивными.

person Bernard Dy    schedule 18.08.2008

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

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

В общем, я бы проголосовал за «в некоторых сценариях они служат определенной цели». Я всегда нервничаю из-за последствий для производительности.

person Blorgbeard    schedule 18.08.2008

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

person Rob Wilkerson    schedule 18.08.2008

Впервые я использовал триггеры пару недель назад. Мы перешли на производственный сервер с SQL 2000 на SQL 2005 и обнаружили, что драйверы по-разному ведут себя с полями NText (сохраняя большой XML-документ), отбрасывая последний байт. Я использовал триггер в качестве временного исправления, чтобы добавить дополнительный фиктивный байт (пробел) в конец данных, решая нашу проблему до тех пор, пока не будет найдено правильное решение.

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

person Anthony K    schedule 18.08.2008

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

person Nick Berardi    schedule 18.08.2008

Что касается сокращения объема работы: базы данных потрясающе эффективны, когда им не приходится иметь дело с внешним миром; вы будете действительно удивлены, насколько даже переключение процессов вредит производительности. Это еще один положительный момент хранимых процедур: вместо дюжины обращений к базе данных (и всех связанных циклических обращений) есть один.

это немного не по теме, но вы также должны знать, что вы смотрите на это только с одного потенциального положительного момента.

Сгруппировать данные в одной сохраненной процедуре - это нормально, но что произойдет, если что-то пойдет не так? Допустим, у вас есть 5 шагов, и первый шаг не удался, что происходит с другими шагами? Вам нужно добавить туда целую кучу логики, чтобы учесть эту ситуацию. Как только вы начнете это делать, вы потеряете все преимущества хранимой процедуры в этом сценарии.

person lomaxx    schedule 18.08.2008

Общий вентилятор,

но на самом деле нужно использовать его экономно, когда,

  • Необходимо поддерживать согласованность (особенно, когда таблицы измерений используются на складе, и нам необходимо связать данные в таблице фактов с их правильным измерением. Иногда правильная строка в таблице измерений может быть очень дорогостоящей для вычисления, поэтому вам нужен ключ Чтобы быть записанным прямо в таблицу фактов, один хороший способ поддерживать эту «связь» - использовать триггер.

  • Необходимо регистрировать изменения (например, в таблице аудита полезно знать, какой пользователь @@ внес изменение и когда оно произошло)

Некоторые СУБД, такие как sql server 2005, также предоставляют вам триггеры для операторов CREATE / ALTER / DROP (чтобы вы могли знать, кто создал какую таблицу, когда, какой столбец, когда и т. Д.)

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

person Community    schedule 18.08.2008

Общее практическое правило: не используйте триггеры. Как упоминалось ранее, они добавляют накладные расходы и сложность, которых можно легко избежать, переместив логику с уровня БД.

Кроме того, в MS SQL Server триггеры запускаются один раз для каждой команды sql, а не для каждой строки. Например, следующий оператор sql выполнит триггер только один раз.

UPDATE tblUsers
SET Age = 11
WHERE State = 'NY'

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

person jinsungy    schedule 18.08.2008
comment
Никогда не используйте курсор в триггере. Да, вам нужно учитывать множественные вставки, обновления или удаления строк, но вам нужно делать это на основе набора. Я удалил курсор из триггера, над которым работаю, и вставка 40 000 записей изменилась с 45 минут до примерно 30 секунд. - person HLGEM; 11.11.2008