|
Программирование >> Программирование баз данных
Мнение автора по этому вопросу, которое уже было высказано в настоящей главе, состоит в том, что триггеры следует использовать строго по назначению. Я не буду чувствовать неловкость, если кто-то отметит, что мое мнение выражено уклончиво и неоднозначно. В программировании и тем более в области разработки приложений для баз данных часто невозможно указать единственно правильный подход. Тем не менее в следующих разделах приведены некоторые факты для размышлений. Выполнение триггеров с отставанием, а не с опережением Триггеры отличаются от таких средств обеспечения целостности данньгх, как ограничения, тем, что выполняются с отставанием, а не с опережением. Под этим подразумевается то, что запуск триггера происходит после осуществления тех действий, с которыми связан триггер. Ко времени запуска триггера завершаются выполнение всего запроса и регистрация транзакции в журнале (но фиксация не происходит и регистрируется только часть транзакции, предшествующая оператору, который вызвал згилуск триггера). Это означает, что если возникнет необходимость осуществить откат в связи с выполнением кода триггера, то может оказаться, что из-за этого придется отменить результаты огромного объема работы, которая уже была проделана, а это приводит к значительному замедлению. Но из-за этого не следует полностью отказываться от использования триггеров. Дело в том, что степень влияния таких последствий существенно зависит от того, насколько большой объем работы предусмотрен в запросе. Рассмотрим, какие следствия вытекают из сказанного. Прежде всего любопытно сравнить то, как используются триггеры, с одной стороны, и ограничения, с другой, учитывая то, что ограничения проверяются заблаговременно. Иными словами, проверка ограничений происходит до того, как начинается выполнение оператора. Это означает, что при использовании ограничений в процессе обработки данньгх заблаговременно обнаруживаются факторы, которые должны стать причиной неудачного завершения, поэтому такое развитие ситуации заранее предотвращается. В связи с этим программное обеспечение, в котором применяются ограничения, обычно функционирует пусть даже ненамного, но быстрее, чем при использовании триггеров, причем по мере усложнения запросов различие в быстродействии увеличивается. Но следует отметить, что такое повышение быстродействия фактически становится достаточно заметным только в тех ситуациях, когда возникают предпосылки применения отката. На основании сказанного выше можно сделать следующий вывод. Если в процессе работы приложения приходится сталкиваться с очень небольшим относительным количеством откатов, а сложность и продолжительность прогона операторов, подверженных откату, невелики, то, по-видимому, различия в быстродействии между триггерами и ограничениями не столь существенны. Разумеется, такие различия всегда обнаруживаются, но, по всей вероятности, не оказывают слишком большого влияния. Но если количество возможных откатов заранее не предсказуемо, а тем более, если известно, что оно должно быть велико, то по возможности следует придерживаться методов обеспечения целостности, основанных на использовании ограничений (и, откровенно говоря, автор рекомендовал бы всегда строить свою работу по обеспечению целостности данных на основе ограничений, если нет достаточно весомых оснований для принятия другого решения). Отсутствие проблем при организации параллельной работы триггеров и процессов, в которых они активизируются По-видимому, читатель обнаружил во многих примерах, приведенных в данной главе, что в них часто используется оператор ROLLBACK, даже несмотря на то, что соответствующий оператор BEGIN TRAN на выполнение не вызывается. Это связано с тем, что триггер всегда неявно становится частью той же транзакции, что и оператор, который вызвал запуск триггера. Если оператор, в котором запускается триггер, не является частью явно заданной транзакции (т.е. транзакции, в которой имеется оператор BEGIN TRAN), то подобный оператор все равно входит в состав собственной транзакции, состоящей из одного оператора. Но в любом случае вызов оператора ROLLBACK TRAN в коде триггера приводит к откату всей транзакции. Еще одним следствием из того, что триггеры рассматриваются как часть одной и той же транзакции, становится наследование триггерами всех блокировок, уже открытых в транзакции, в состав которой они входят. Это означает, что в коде триггера не требуется предпринимать каких-либо особых действий для предотвращения возможности конфликта с блокировками, созданными в других операторах той же транзакции. В коде триггера предоставляется свободный доступ ко всем объектам данных, принадлежащим к области определения транзакции, кроме того, в коде триггера наблюдается такое состояние базы данных, в котором учтены все модификации, внесенные в данные предыдущими операторами транзакции. Применение триггеров с небольшим объемом кода Безусловно, рекомендации, приведенные в этом разделе, представляют собой повторение ранее высказанных рекомендаций, но автор обязан их повторить, поскольку для этого есть весомые основания. Сложно даже представить себе, насколько часто в процессе изучения существующих программ приходится сталкиваться с хранимыми процедурами и триггерами, содержащими раздутый и непродуманный код. Нелегко понять, чем руководствуются программисты, создающие подобные программы, - либо они хотят лишь скорее закончить работу, либо считают, что СУБД и так работает достаточно быстро, поэтому не нужно заботиться о повышении быстродействия. Следует помнить, что триггер - это такая же часть транзакции, как и оператор, из которого он вызван. Это означает, что вьшолнение оператора транзакции не заканчивается до тех пор, пока не завершится вьшолнение триггера. Из этого следует, что если для вьшолнения кода, содержащегося в триггере, потребуется много времени, то, в свою очередь, будет занимать много времени вьшолнение каждого фрагмента созданного вами кода, который вызывает запуск триггера. В связи с этим возникают буквально непреодолимые трудности при попытке понять, почему на вьшолнение кода затрачивается так много времени. На первый взгляд кажется, что написанная хранимая процедура должна быть чрезвычайно эффективной, но на самом деле обнаруживается, что ее производительность неприемлема. Вы можете биться над этой проблемой неделями, но так и не понять, что проблема заключается не в самой хранимой процедуре, - в ней просто происходит запуск триггера, имеющего чрезвычайно низкую производительность. Выбор индексов с учетом наличия триггеров Еще одна распространенная опшбка заключается в том, что при выборе индексов забывают о существовании триггеров. Разработчик просматривает все свои хранимые процедуры и представления, определяя, какое сочетание индексов является наилучшим, и полностью забывает о том, что значительная часть кода выполняется в виде триггеров. В данном случае действует такой же принцип, который был описан в разделе Применение триггеров с небольшим объемом кода , - в операторах вызываются запросы, выполнение которых занимает много времени, поэтому сами эти операторы долго не заканчивают свою работу, а это, в свою очередь, приводит к общему замедлению функционирования всех приложений. Занимаясь оптимизацией кода, не забывайте о триггерах! Отказ от применения операторов отката в коде триггеров Безусловно, эту рекомендацию нелегко осуществить на практике, поскольку откаты слишком часто составляют основную часть тех действий, которые требуется осуществить в триггерах. Но следует помнить, что триггеры AFTER (которые бесспорно являются самым распространенным типом триггеров) вызываются на выполнение после того, как основная часть работы уже проделана, а это означает, что операция отката становится дорогостоящей. Именно в этих обстоятельствах декларативные средства поддержки целостности проявляют все свои преимущества, непревзойденные с точки зрения производительности. Если в триггерах приходится использовать много операторов ROLLBACK TRAN, то следует предусмотреть заблаговременную проверку на наличие всех возможных ошибок, прежде чем вызывать на выполнение оператор, в котором происходит запуск триггера. Иными словами, возьмите на себя заботу по осуществлению превентивньгх мер, поскольку сама СУБД SQL Server в этой ситуации их не осуществляет. Не дожидаясь отката, заранее проверяйте, будут ли возникать ошибки. Удаление триггеров Для удаления триггеров применяется такой же простой оператор, как и почти все описанные до сих пор операторы удаления: DROP TRIGGER <trigger name> После выполнения оператора удаления триггер становится недоступным. Отладка триггеров Попытка перейти в отладчике к триггеру по такому же принципу, как происходит переход к хранимой процедуре (см. главу 11) или функции, оканчивается неудачей, поскольку возможность непосредственной отладки кода триггера с помощью отладчика не предусмотрена. Тем не менее процедура отладки триггера является сложной, поэтому желательно применить для этой цели другой способ использования отладчика. Один из таких способов описан ниже. Безусловно, его нельзя назвать очень изящным, но он вполне применим. По существу для реализации этого способа необходимо создать вспомогательную хранимую процедуру, в которой осуществляется запуск отлаживаемого триггера. Единственное назначение этой хранимой процедуры состоит в том, что она обеспечивает вызов на выполнение оператора, который позволяет войти в отладчике в код триггера.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |