Предупреждение о блокировках в SQL Server

Tags: SQL Server

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

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

Блокировка - это хорошо. Чрезмерная блокировка - это плохо.

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

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

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

Какое вам нужно оповещение?

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

  1. Предупреждение необходимо, если на самом деле есть проблема, которая может быть выполнена. Пожалуйста, не бросайте по электронной почте предупреждения, если ничего нельзя сделать. Не будь мальчиком, который кричал “Волк!” Возможно, у вас уже есть правило электронной почты, которое игнорирует предупреждения, которые вам не нужны. Не делайте больше спама.
  2. Предупреждение необходимо, только если проблема критическая. В дополнение к требованию № 1, чтобы оно было действенным, нужно чтобы оно побуждало к сиюминутному действию. Уведомления по электронной почте - это крик о помощи и не подходят для каждой проблемы. Для проблем с более низким приоритетом лучше использовать отчеты дайджеста, где вы можете выделить время в свой день для работы над многими проблемами с более низким приоритетом и сразу же позаботиться о них.
  3. Дайте мне всю необходимую информацию и только ее. Суббота, 9 часов вечера, и в вашей базе данных начинают выскакивать оповещения, пока вы расслабленно попиваете коктейль. Крайне важно, чтобы вы могли сортировать проблемы непосредственно из предупреждения и в идеале предпринимать действия, не выполняя кучу исследований, чтобы выяснить, что делать.
  4. Оповещайте быстро. Мы уже установили, что имеем дело с критическими проблемами - если это важно, тогда мне нужно знать сейчас. Лучше узнать о проблеме самостоятельно, чем от конечных пользователей, чтобы исправить ее до того, как кто-то еще заметит.
  5. Не переусердствуйте. Сколько оповещений по электронной почте вам нужно об одной и той же проблеме? Скорее всего, нет необходимости  отправлять электронное письмо каждые 30 секунд, но также может быть полезно периодически предупреждать, чтобы вы знали, что проблема не решена.

Требований не так много, но они нуждаются в некотором объеме дополнительной работы.

Давайте создадим оповещение

Определяем действующие проблемы

Мы уже сделали тяжелую работу в dbo.Check_Blocking, чтобы идентифицировать чрезмерную блокировку. Когда у нас есть чрезмерная блокировка, действие, вероятно, должно уничтожить  сеанс или остановить процесс подачи заявки или сообщить сотруднику об остановке.

Определяем критические проблемы

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

Получение правильных точек данных

Мы уже проделали работу с процедурой dbo.Check_Blocking, чтобы получить правильные точки данных, поэтому мы закончили с этим, правильно? Не так быстро, у нас тут больше работы.

Мы будем использовать функцию dbo.EmailCss () из этой записи, чтобы форматировать электронную почту. CSS, созданный этой функцией, будет определять стили для шрифтов и форматирование для HTML-таблиц. Это поможет убедиться, что мы не только представляем правильную информацию, но и делаем это так, чтобы ее легко воспринимать.

 

В процедуре dbo.Check_Blocking мы использовали поле XML для SessionInfo для всех сеансов, участвующих в цепочке блокировки. Мы собираемся внести некоторые изменения в этот код, и на этот раз мы собираемся сгенерировать HTML, включая некоторое форматирование, чтобы убедиться, что все в порядке:

 


-- Populate SessionInfo column with HTML details for sending email


-- Since there's a bunch of logic here, code is more readable doing this separate than mashing it in with the rest of HTML email creation


UPDATE lb


SET SessionInfo = '<span style="font-weight:bold">Login = </span>' + LoginName + '<br>' +


                              CASE WHEN TransactionCnt <> 0


                                    THEN '<span style="font-weight:bold">Transaction Count = </span>' + CAST(TransactionCnt AS nvarchar(10)) + '<br>'


                                    ELSE ''


                               END +


                               CASE WHEN WaitResource <> ''


                                    THEN '<span style="font-weight:bold">Wait Resource = </span>' + COALESCE(WaitDescription,WaitResource) + '<br>'


                                    ELSE ''


                               END +


                               '<span style="font-weight:bold">Host Name = </span>' + HostName + '<br>' +


                               CASE WHEN DbName <> ''


                                    THEN '<span style="font-weight:bold">DbName = </span>' + DbName + '<br>'


                                    ELSE ''


                               END +


                                  '<span style="font-weight:bold">Last Request = </span>' + CONVERT(varchar(20),LastRequestStart,20) + '<br>' +


                                  '<span style="font-weight:bold">Program Name = </span>' + ProgramName + '<br>'


FROM #LeadingBlocker lb;

UPDATE b


SET SessionInfo = '<span style="font-weight:bold">Login = </span>' + LoginName + '<br>' +


                            '<span style="font-weight:bold">Host Name = </span>' + HostName + '<br>' +


                            CASE WHEN TransactionCnt <> 0


                                THEN '<span style="font-weight:bold">Transaction Count = </span>' + CAST(TransactionCnt AS nvarchar(10)) + '<br>'


                                ELSE ''


                          END +


                          CASE WHEN WaitResource <> ''


                                THEN '<span style="font-weight:bold">Wait Resource = </span>' + COALESCE(WaitDescription,WaitResource) + '<br>'


                                 ELSE ''


                          END +


                          '<span style="font-weight:bold">DbName = </span>' + DbName + '<br>' +


                          '<span style="font-weight:bold">Last Request = </span>' + CONVERT(varchar(20),LastRequestStart,20) + '<br>' +


                          '<span style="font-weight:bold">Program Name = </span>' + ProgramName + '<br>'


FROM #Blocked b;

Есть еще одна важная информация, которую нам нужно добавить в наши оповещения. Какой SQL-экземпляр отправляет эти предупреждения? Если это экземпляр отказоустойчивого кластера, на каком узле работает экземпляр? Был ли он перезапущен недавно? Каково время запуска экземпляра? Подобно тому, как мы используем функцию для генерации стандартного CSS, я использую функцию для создания стандартного нижнего колонтитула dbo.EmailServerInfo_Get ().

Обратите внимание, что для этого FCI сервер и экземпляр - разные.

Быстрое оповещение

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

Для большинства людей «планирование задания» означает настройку задания агента SQL для запуска процедуры. Если вы используете Azure SQL DB (у которого нет ни DB Mail, ни SQL Agent), или же если вы просто любите PowerShell, вы можете использовать егоl для централизованного запуска этого предупреждения и отправки электронных писем. ( В этом случае просто запустите процедуру с @ Debug = 2. С этим значением параметра процедура просто возвращает однострочный набор результатов с одним столбцом, который является блоком HTML. Просто используйте этот HTML-блок как тело вашей электронной почты и отправьте его вместе с PowerShell.

Не перегружайте оповещениями

Когда мы сказали, чтобы вы планировали, чтобы задание выполнялась каждую минуту,  это вовсе не означает, что при возникновении блокировки вы будете получать письмо на электронную почту каждую минуту. Каждый раз, когда dbo.Alert_Blocking отправляет электронное письмо, он записывает его в таблицу (dbo.Monitor_Blocking). Каждый раз, когда он идентифицирует блокировку, он проверяет эту таблицу, чтобы узнать, когда она отправила уведомление по электронной почте. Если он недавно отправил электронное письмо, он откладывает повторные оповещения. Параметр @EmailThreshold определяет время, на которое вы хотите отложить оповещения. Просто укажите, сколько минут необходимо между сообщениями электронной почты. В качестве бонуса эта таблица может использоваться как машина времени, чтобы оглядываться назад на проблемы блокировки с течением времени.

 

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

Если вы установите нашу полную базу данных DBA, у вас есть все, что вам нужно. Инструкции по установке всего этого в README проекта. Если вы хотите установить только бит для этого предупреждения, вам потребуется несколько объектов из этого проекта:

dbo.EmailCSS_Get () - эта скалярная функция обеспечивает CSS, чтобы сообщения электронной почты были хорошо отформатированы и легко читаемы.

dbo.EmailServerInfo_Get () - эта скалярная функция предоставляет HTML для нижнего колонтитула электронной почты со стандартной информацией о сервере.

dbo.Monitor_Blocking - это таблица, используемая для дроссельной почты и для исторических целей.

dbo.Alert_Blocking - это процедура, которая фактически выполняет эту работу, и процедура,  которую вы будете планировать для отправки своих оповещений.

Теперь, когда он установлен, давайте посмотрим предупреждение.

Вот пример электронной почты, показанный в приложении Outlook 2016 Desktop, и Outlook для Android:

Помните: если разработчик вызывает блокировку, завершите сеанс, не убивайте разработчика.

No Comments

Add a Comment