Являются ли триггеры базы данных злыми? [закрыто]

187

Являются ли триггеры базы данных плохой идеей?

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

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

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

WW.
источник
31
Это совершенно законный вопрос, но мне не нравится сенсационный титул. Я думаю что-то вроде «Какие наиболее важные вопросы следует учитывать при реализации триггеров базы данных?» было бы намного лучше.
Тамас Чинеге
2
Вопрос закрыт для добавления ответов, но см. Также Безопасны ли триггеры базы данных для ограничений целостности таблиц? , (Спойлер: нет, это не так)
Mifeet
16
Этот сайт меня бесит. Это БОЛЬШОЙ вопрос, но, как и многие другие, он закрыт, потому что людям не хватает воображения, чтобы принять вопросы, которые не вписываются в примитивный двоичный формат вопросов и ответов, которым они по какой-то чуждой причине считают себя обязанными следовать.
Ужасно
1
Бизнес-логика в триггере проблематична (зло, если хотите). Логика базы данных в триггере не представляет проблем (целостность, ведение журнала).
Грег Гам
1
Мне нравится полагаться на IDE для навигации по коду и понимания происходящего. Я не могу этого сделать, если половина логики находится в базе данных, а другая половина на выбранном языке программирования. Вместо триггеров мне проще создать контроллер, через который должен проходить каждый запрос. Все «триггеры» могут быть применены там вместо этого.
Мухаммед Умер

Ответы:

147

Основные проблемы с триггерами

  • Они полностью глобальны - они применяются независимо от контекста активности за столом;
  • Они скрытны; легко забыть, что они там, пока они не причинят вам вред непреднамеренными (и очень загадочными) последствиями.

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

dkretz
источник
20
Это два преимущества, в некоторых случаях.
Джонно Нолан
18
«Stealthy» - отличное слово, да, - хорошо сказано. Именно поэтому я склонен уклоняться от них: слишком часто они забываются или игнорируются. По моему личному опыту, повторный запуск триггера часто сопровождается ударом в лоб.
Кристиан Нунциато
5
Глобальность - это то, почему они хороши и необходимы для целостности данных и таких вещей, как аудит. Это не минус, это плюс.
HLGEM
4
так @ RobertŠevčík-Robajz, вы говорите, что все разработчики, которых вы знаете, некомпетентны?
HLGEM
3
@ ХЛЕГМ, согласись, там должен быть специалист для проработки триггеров. Реальный сценарий жизни - нет. Сценарий из реальной жизни - дни, потраченные на поиск ошибки, связанной с забытым триггером. Реальный сценарий - логика триггера отчаянно вытесняется в логику приложения, где она может быть легко реорганизована и протестирована модульно. Это реальная жизнь, с которой я сталкиваюсь, заставляет меня говорить «держись подальше от триггеров» ... это не вина триггеров, так как это не вина камней, которые разбивают окна.
Rbjz
80

Нет, они на самом деле хорошая идея. Если есть проблема с вашими определенными триггерами, то вы делаете их неправильно, но обычно это означает, что есть проблема с вашей реализацией, а не с концепцией самих триггеров :-).

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

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

Кроме того, отсутствие триггеров помешает применению правил данных в СУБД, таких как предварительные триггеры, для обеспечения того, чтобы столбцы имели определенный формат. Обратите внимание, что это отличается от правил целостности данных, которые обычно являются просто поисками внешнего ключа.

paxdiablo
источник
9
msgstr "обработать функцию в каждой строке при их выборе". Для этой цели лучше использовать индекс на основе функции, чем триггер.
Tuinstoel
10
Не обязательно, триггер, вероятно, будет работать только тогда, когда строка вставлена ​​или обновлена. Индекс на основе функций будет выполняться для каждого выбора. В зависимости от модели использования одно, вероятно, лучше другого. Но ни один не всегда лучше, чем другие.
jmucchiello
@tuinstoel: Я должен согласиться с твоим утверждением иногда . Например, Oracle будет создавать индексы на основе функций только в том случае, если сможет доказать, что функция является детерминированной. Иногда это просто невозможно доказать (например, если функция включает поиск по таблице, даже если вы знаете, что данные таблицы никогда не изменяются).
Адам Пейнтер
50

Инструменты никогда не являются злыми. Применение этих инструментов может быть злым.

Энди Уэбб
источник
11
Я никогда не был более противоречивым после прочтения комментария. С одной стороны, я выступаю за вторую поправку и считаю, что оружие не является злым по сути: это человек, использующий его. С другой стороны, я считаю, что это ЗЛО ... Я думаю, что у меня экзистенциальный кризис ...
vbullinger
37
Оружие @vbullinger не зло, но их спусковые механизмы;)
Дарра Энрайт
2
Обобщения опасны (рекурсивно). Пришли ли вы с помощью «инструментов» пыток, используемых инквизиторами, чтобы «вызвать» признание? +1 за перспективу в любом случае.
Rbjz
22

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

Важность триггеров (на мой взгляд) заключается в том, что ...
- Любая система всегда должна быть в допустимом состоянии.
- Код для обеспечения соблюдения этого допустимого состояния должен быть централизованным (не записанным в каждом SP).

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

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

Они звучат резко, и я думаю, что они есть. Но это основная истина, на мой взгляд ...

MatBailie
источник
3
>>> Проблемы с триггерами это люди. Да, если бы только люди могли писать код на ассемблере, работать с дерьмовым графическим интерфейсом, правильно угадывать, толкать или тянуть плохо спроектированную дверь ... Любая «особенность», которую люди неоднократно ошибаются, - это «зло».
Факрудин
1
@Fakrudeen, любой разработчик, который ошибается триггерами, некомпетентен для доступа к базе данных.
HLGEM
21

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

HLGEM
источник
1
Данные-ориентированные правила принадлежат базе данных
абсин
был яsome programmers are too ethnocentric to consider that something other than their prized application may be affecting things
Kid101
13

В основном да.

Сложность с триггером в том, что он делает вещи «за спиной»; разработчик, поддерживающий приложение, может легко не понять, что оно там, и внести изменения, которые все испортили, даже не заметив.

Это создает уровень сложности, который просто добавляет работы по обслуживанию.

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

MarkR
источник
12
В этом преимущество триггера, а не развала! Нельзя гарантировать, что хранимые процедуры будут вызываться при каждом изменении данных. Существует множество способов изменения данных помимо графического интерфейса.
HLGEM
2
HLGEM, это зависит от вашего контроля доступа. Вы можете запретить любое изменение таблиц напрямую, кроме как через хранимую процедуру.
Rbjz
1
Я думаю, что дело в том, что если, например, записи в двух таблицах ВСЕГДА должны создаваться и уничтожаться вместе, независимо от того, как вы обращаетесь к базе данных, и неважно, кто вы и какие у вас права доступа, триггеры являются единственным законным решением. , Сам факт того, что это даже можно назначить слишком много или неправильные разрешения и ожидать , что люди знать , какие хранимые процедуры должны быть использованы, означает , что база данных рискует потерять свою целостность. Это точно так же, как отношения с внешним ключом. Это просто ЛУЧШИЙ и НАДЕЖНЫЙ, обеспеченный механизмом базы данных.
Трийнко
2
Если записи всегда должны создаваться / уничтожаться вместе, создайте проверочное ограничение, которое гарантирует, что они есть. Таким образом, тот, кто нарушает правила, получает ошибку, а не скрытое поведение, которое волшебным образом исправляет ситуацию без их ведома или согласия.
MarkR
9

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

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

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

Робин Дэй
источник
7

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

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

Существует также «принцип наименьшего удивления», о котором уже упоминалось.

Дейв Шерохман
источник
3
Это правильно, это должно быть в одном месте, в базе данных. Логика, которая влияет на целостность данных, должна ВСЕГДА находиться в базе данных, а не в приложении, где она может вызываться или не вызываться при воздействии на данные в базе данных.
HLGEM
1
@HLGEM: Это зависит от того, может ли база данных иметь доступ к информации, которая позволяет ей определить, являются ли данные действительными. Это не всегда так. когда валидатор находится в другой организации (например, для кредитной карты или реквизитов банковского счета), то БД не может знать, правильно ли это - предполагая, что это не БД банка! - и ему придется полагаться на заявление о принудительном исполнении. Чего вы не хотите, так это чтобы база данных выполняла произвольные подключения к сторонним сервисам, поскольку это плохо для развертывания сервера.
Донал Феллоуз
@HLGEM: Хотя я не готов полностью исключить возможность размещения всей логики приложения в базе данных, я обнаружил, что она лучше работает, когда помещает ее в другое место, как правило, это ОО-слой многократного использования, который можно использовать для доступа всех приложений. база данных. До тех пор, пока ваше приложение получает доступ к базе данных только через объектный уровень, будут действовать те же гарантии всегда вызываемой логики.
Дейв Шерохман
2
Никогда не работал над бизнес-приложением, которое вставляло данные в базу данных только через слой объектов, и я не хочу работать над ним. Глупо размещать миллионы записей об импорте или обновлениях всех цен через процесс, предназначенный для обработки только одной записи за раз. Уровень объектов - это как раз неподходящее место для обеспечения целостности данных, поэтому у многих баз данных возникают проблемы с целостностью.
HLGEM
@HLGEM Именно по этой причине я работаю над расширением нашего ORM, чтобы оно работало как триггер, используя набор изменений всего внутри транзакции. Это кажется немного глупым, но помешает нам иметь всю нашу бизнес-логику в приложении, за исключением нескольких раз, когда это не так (только несколько таблиц когда-либо нуждаются в массовом обновлении). Это также позволит всем разработчикам писать и использовать их на языке, который им наиболее удобен, и где есть доступ ко всем построенным нами абстракциям объектов.
Адамантиш
6

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

Теперь они могут быть «злыми», если вы попадете в «адский триггер» с одним триггером, который запускает другие триггеры. Однажды я работал над продуктом COTS, где у них было то, что они называли «триггерами гибкого трубопровода». Эти триггеры были сохранены в таблице, так как динамические строки SQL были скомпилированы каждый раз, когда они выполнялись. Скомпилированные триггеры просматривают и проверяют, есть ли в этой таблице какие-либо триггеры flex для запуска, а затем компилируют и запускают триггер «flex». Теоретически это звучало как очень крутая идея, потому что продукт был легко настроен, но реальность заключалась в том, что база данных взорвалась из-за всех компиляций, которые она должна была делать ...

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

tmeisenh
источник
6

На высоком уровне есть два варианта использования триггеров1

1) Чтобы все происходило «автоматически». В этом случае триггеры вызывают побочный эффект, они изменяют данные способами, которые не ожидались, учитывая (примитивный) оператор вставки, обновления или удаления, который был выполнен и вызвал срабатывание триггера.

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

2) Для обеспечения соблюдения правил целостности данных, кроме тех, с которыми мы можем обращаться декларативно (используя CHECK, PRIMARY KEY, UNIQUE KEY и FOREIGN KEY). В этом сценарии использования все триггеры - это данные QUERY (SELECT), чтобы проверить, разрешено или нет изменение, вносимое INSERT / UPDATE / DELETE. Так же, как декларативные ограничения делают для нас. Только в этом случае мы (разработчики) запрограммировали правоприменение.

Использование триггеров для последнего варианта использования не является вредным.

Я веду блог по этому адресу: http://harmfultriggers.blogspot.com

Тун Коппелаарс
источник
При использовании триггеров для ссылочной целостности сложнее, чем кажется, решать проблемы параллелизма.
WW.
2
Согласовано. Но легче ли использовать какие-то другие средства?
Мун Коппелаарс
Я бы сказал, что номер один вреден, только если у вас есть некомпетентные разработчики.
HLGEM
Есть много некомпетентных разработчиков, хотя LOL.
hashtable
5

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

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

DanSingerman
источник
За исключением того, что вся работа по попаданию в базу данных проходит через код приложения.
HLGEM
5

Не зло Они на самом деле упрощают такие вещи, как

1. Регистрация / аудит изменений в записях или даже схемах баз данных.

У вас может быть триггер ALTER TABLE, который откатывает изменения в вашей производственной среде. Это должно предотвратить любые случайные модификации таблицы.


2. Обеспечение ссылочной целостности (отношения первичного / внешнего ключа и т. Д.) В нескольких базах данных.

Крис
источник
Вы можете откатить операторы DDL?
Эндрю Свон
Вообще нет. Единственный способ остановить это - удалить это разрешение из логинов пользователей.
jmucchiello
В некоторых системах баз данных вы можете (например, PostgreSQL).
Николас
@ Андрей - в SQL Server вы можете. SQL Server 2005+ также имеет триггеры DDL, которые запускаются при таких событиях, как ALTER TABLE.
Мартин Смит
4

Нет, они не злые - их просто неправильно поняли :-D

Триггеры имеют правильное применение, но слишком часто как ретро-хак, который в конечном итоге ухудшает ситуацию.

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

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

Кит
источник
4

Сказать, что они злые, - это преувеличение, но они могут стать причиной меша. Когда срабатывание одного триггера вызывает срабатывание других триггеров, это становится действительно сложным. Допустим, они хлопотны: http://www.oracle.com/technology/oramag/oracle/08-sep/o58asktom.html

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

tuinstoel
источник
4

Они определенно не злые. Я нашел триггеры полезными при рефакторинге схем базы данных, при переименовании столбца или разделении столбца на два столбца или наоборот (пример: регистр имени / фамилии) и при содействии перехода.

Они также очень полезны для аудита.

Стефано Борини
источник
4

Этот ответ относится конкретно к SQL Server. (хотя это может также относиться к другим СУБД, я понятия не имею. Я бы предпочел дать здесь ответ, но это было закрыто, как обман.)

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

Пример, приведенный в BOL под заголовком « Управление безопасностью триггера », относится к пользователю, который создает триггер, содержащий код GRANT CONTROL SERVER TO JohnDoe ;, для повышения своих собственных разрешений.

Мартин Смит
источник
3

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

Xn0vv3r
источник
3

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

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

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

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

Аарон Пауэлл
источник
1

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

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

IBZ
источник
1

Идея триггеров - не зло, ограничение вложенности триггеров - зло.

alpav
источник