Как в last учитывать длительность zabbix
Перейти к содержимому

Как в last учитывать длительность zabbix

  • автор:

Триггер и сценарий для опроса сайта. Zabbix

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

>0 and >0 

Отслеживать
kiryushinsa
задан 20 мар 2020 в 7:06
kiryushinsa kiryushinsa
55 7 7 бронзовых знаков

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Дальше. Например для Zabbix server:web.test.fail[http://vsks.ru/] Можно взять функцию min. Будет выглядеть так:

Т.е. для web.test.fail нормальное значение равно 0, а значение больше 0, это шаг проверки на котором произошла ошибка. Тогда min(10m)>>0 сработает тогда, когда минимальное значение будет больше 0 в течении 10 минут. Здесь следует учитывать, что если сайт будет постоянно переходить между состояниями доступен\не доступен, этот триггер не сработает.

Второй вариант. Использовать функцию count

Здесь нужно учитывать переодичность проверки. предположим — 1 раз в минуту. Сработает когда за последних 10 минут будет больше 6 значений, отличных от 0.

Zabbix. Правила автообнаружения

Zabbix — это open source система мониторинга, универсальный инструмент для отслеживания работы серверного и сетевого оборудования, сервисов и приложений. В нашем банке на мониторинге zabbix стоит более 4000 хостов, на большинстве хостов реализованы уникальные проверки. По триггерам многих хостов рассылки происходят на разные группы оповещений, то есть с одного хоста оповещения о разных триггерах рассылаются на разные группы. В связи с этим мы только планируем переход на более новую версию zabbix.

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

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

В данной статье будет рассмотрено автообнаружение на примере мониторинга учетных записей в AD с подробными объяснениями, как это можно использовать для других целей. Рецепт https://github.com/asand3r/zbx-adusers мне не подошел. Задача следующая: у разных подразделений есть технические доменные учетные записи (их немного). У учетных записей может истечь пароль, их могут просто отключить, или они могут заблокироваться, и тогда сервис остановится. Нужно средствами в заббикс мониторить количество дней до истечения пароля и другие важные свойства, и оповещать конкретные подразделения по разным каналам. Кроме того, нужно все это выводить на разные дашборды в графане, чтобы владельцы учетной записи могли видеть нужные свойства всегда, а не только в течение 90 дней до истечения пароля. У нас сроки пароля разные для разных (УЗ) учетных записей. Но повторюсь, суть не в моей задаче. А в том, как использовать автообнаружение для своей задачи, как изобрести свой конкретный велосипед, когда магазинные в чем-то не устраивают.

Давайте рассмотрим, в каких ситуациях стоит использовать автообнаружение.

Условие: Объекты должны быть однотипные, и нам нужно мониторить какое-то одно и то же свойство у каждого.

Когда стоит использовать автообнаружение:

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

Шаги автообнаружения.

1. Что собственно будем мониторить.

Берем один объект из нашего списка и создаем для него метрику. Например, нам нужно мониторить срок истечения пароля учетной записи. Берем тестовую учетную запись и думаем, как нам узнать, когда же истечет пароль. У меня есть удобный скрипт для этих целей. Нужно добавить, что мониторим мы с сервера (назовем его SERVER1), введенного в домен. Заббиксагент на нем запущен от доменной УЗ, которая имеет соответствующие права).

Get-ADUser -Identity petrov_pp -Properties msDS-UserPasswordExpiryTimeComputed,PasswordNeverExpires,Enabled,LockedOut| Select-Object PasswordNeverExpires,@>,Enabled,LockedOut|Convertto-json

Кроме срока истечения пароля по этому скрипту мы получаем еще ряд важных параметров:

  • PasswordNeverExpires – истекает ли вообще пароль.
  • RemainingDays – сколько дней осталось до истечения пароль.
  • Enabled – включена ли УЗ (административно).
  • LockedOut – заблокирована ли УЗ.

Теперь нам нужно как-то заставить заббикс запустить этот скрипт самому. Для этого в zabbix_agentd.conf на сервере SERVER1 добавляем userparameter:

UserParameter=account[*],C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -Command «Get-ADUser -Identity $1 -Properties msDS-UserPasswordExpiryTimeComputed,PasswordNeverExpires,Enabled,LockedOut| Select-Object PasswordNeverExpires,@>,Enabled,LockedOut|Convertto-json»

Обратите внимание на следующие моменты:

  1. account[*] . Слово «account» – это мы сами придумываем, но это тот самый ключ, который будет дергать заббикс. После чего заббикс-агент будет запускать команду после запятой. * указывает на то, что вместо нее можно вставить любое значение. На это значение будет заменено $1 в скрипте. Например, если мы в заббиксе укажем ключ account[petrov_pp] , заббикс агент запустит указанный выше скрипт для -Identity petrov_pp .
  2. Все двойные кавычки внутри скрипта должны быть экранированы. Это крайне важно!

Итак, у нас есть рабочая метрика. Теперь нужно заббиксу сообщить, какие же объекты ему нужно создать.

2. Найти объекты автообнаружения.

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

На нашем примере по учетным записям исходно такого объекта нет. Подразделения сами обращаются и просят мониторить конкретные УЗ. Мы можем создать файлик на нашем SERVER1 со списком этих УЗ определенного формата. Файлик этот нужно положить в ту папку, которую может читать zabbix agent на хосте. Метрика заббикса будет этот список читать и получать нужную информацию.

  • Name accounts_txt ;
  • Type Zabbix agent ;
  • Key vfs.file.contents[C:\Zabbix\Scripts\accounts.txt] .

Но как заполнять этот файлик? Как привести эти данные к нужному формату?

Заббикс хорошо понимает формат json:

Здесь у нас представлены две переменные и . Это макросы, которые мы сможем использовать в прототипах метрик и триггеров.

Всего в этом примере три объекта, у каждого объекта по два свойства. Первый объект – это «: «petrov_pp»,»»: «otdel1″>. В данном случае имя учетной записи petrov_pp, а второе свойство нам понадобиться для триггеров.

Таким образом, мы можем создать файлик такого формата и добавлять в него новые объекты. Но вдруг сотрудник, который будет добавлять, ошибется в скобочках? И всё разом сломается.

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

Файл следующего вида:

petrov_pp otdel1 smirnov_ii otdel2 ivanov_mm otdel3

Далее делаем препроцессинг для этой метрики с помощью javascript.

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

var str_new=value.replace(/\r\n/g,',') var str_new1=str_new.replace(/ /g,';') var str_new2=str_new1.replace(/\,/g,'">, ": "') var str_new5=str_new2.replace(/;/g,'","": "') var strnew3 = "\\"\: \""; strnew3 += str_new5; strnew3 += "\"\>]\>"; return strnew3

Немного о функции замены.

value – переменная, в которой текст, подлежащий замене. Изначально, всё, что получила метрика заббикс, попадает в переменную value.

Рассмотриv, что на что заменяется на примере ( /aaa/g,’bbb’ ).

aaa — то, что хотим заменить. Часто нужно экранировать спецсимволы обратной коcой чертой \ .

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

bbb – на что хотим заменить.

g – заменять столько раз, сколько встречается выражение aaa .

Теперь рассмотрим код скрипта по строкам:

Строка 1. в переменную str_new записыванием исходный текст, в котором все enter заменены запятыми. Шаг необязательный, но захват нечитаемых символов очень неочевидная вещь. Если мы просто попытаемся протестировать работу этой строки на тексте из latest data заббикса, то не получим нужный результат. А вот если скопируем из блокнота на SERVER1, то получим. Вот такая особенность. В latest data не всегда точно отображается то, что получает метрика.

Строка 2. Заменяем все пробелы на точку с запятой.

Строка 3. Заменяем все запятые на » >, «: «

Строка 4. Также производим замену, аналогично строке 3.

Строки 5-7: собираем в переменную strnew3 по порядку указанные значения.

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

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

3. Создать правила автообнаружения.

В zabbix на SERVER1 создаем новое правило автообнаружения. Правило автообнаружения – это по сути та же метрика, результат которой мы непосредственно посмотреть не можем. Поэтому я всегда делаю ее зависимой метрикой. В данном случае, это зависимая метрика от accounts.txt.

  • Name accounts_discovery ;
  • Type Dependent item ;
  • Key accounts_discovery ;
  • Master item SERVER1: accounts_txt ;
  • Keep lost resources period 1h .

Период сохранения потерянных ресурсов следует выбирать исходя из задачи.

Вопрос: где стоит прикручивать препроцессинг? На правиле обнаружения или на исходной метрике?

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

4. Создать прототипы метрик и триггеров.

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

Имеет смысл сделать основной прототип метрики, которая возвращает все эти данные, и 4 зависимых прототипа метрик.

Основной прототип метрики:

  • Name ;
  • Type Zabbix agent ;
  • Key account[] .

Также можно добавить прототип приложения. То есть все наши 5 метрик будут в одном приложении, которое будет носить имя УЗ. Это удобно для отображения результатов в grafana.

New application prototype

Я предпочитаю переводить такого рода данные в нормальный Json format следующим скриптом препроцессинга (javascript).

var strnew = "\"; return strnew;

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

Далее необходимо создать еще 4 прототипа метрик.

Для метрики по определению включена УЗ или нет, например:

  • Name Enabled ;
  • Type Dependent item ;
  • Key Enabled_[] ;
  • Master item SERVER1: ;
  • Application prototypes .

Обратите внимание, здесь в качестве master item выбираем item prototype .

В препроцессинге выбираем Jsonpath $.data[0].Enabled .

Давайте рассмотрим наш итоговый вывод по конкретной УЗ:

У нас здесь один объект с четырьмя свойствами. Наш Jsonpath берет нулевой объект (отсчет идет с нуля) и считывает значение свойства Enabled .

Если бы у нас было несколько объектов в <> через запятую и нам нужно было бы свойство LockOut третьего, например, объекта, мы бы написали:

В нашем случае объект один, поэтому в квадратных скобках будет только 0, а меняться будет только последнее слово.

Например, метрика по количеству дней до истечения пароля будет иметь следующий препроцессинг:

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

После создания всех нужных прототипов метрик нужно создать прототипы триггеров на свой вкус.

А теперь для чего же мы вводили ?

У нас триггеры по одному серверу направляются на разные группы оповещения исходя из trigger tag. Изменить или добавить тег в триггер, созданный автообнаружением, невозможно. Поэтому добавляем его здесь.

Мы могли бы добавить третью переменную и писать что-нибудь в комментарий.

Заключение

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

Использование Zabbix для слежения за базой данных MS SQL Server

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

В данной статье будет описано, что необходимо настроить в Zabbix для слежения за базой данных MS SQL Server.

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

Решение

    Logical Disk

      Avg Disc sec/Read
      Показывает выраженное в секундах среднее время чтения данных с диска. Среднее значение счетчика производительности Avg. Disk sec/Read не должно превышать 10 миллисекунд. Максимальное значение счетчика производительности Avg. Disk sec/Read не должно превышать 50 миллисекунд.

    Zabbix: perf_counter[\LogicalDisk(_Total)\Avg. Disk sec/Read], а также важно проследить за нужным диском, например так: perf_counter[\LogicalDisk(C:)\Avg. Disk sec/Read]

    Zabbix: perf_counter[\LogicalDisk(_Total)\Avg. Disk sec/Write], а также важно проследить за нужным диском, например так: perf_counter[\LogicalDisk(C:)\Avg. Disk sec/Write]

    Cредняя длина очереди запросов к диску. Отображает количество запросов к диску, ожидающих обработки в течении определенного интервала времени. Нормальным считается очередь не больше 2 для одиночного диска. Если в очереди больше двух запросов, то возможно диск перегружен и не успевает обрабатывать поступающие запросы. Уточнить, с какими именно операциями не справляется диск, можно с помощью счетчиков Avg. Disk Read Queue Length (очередь запросов на чтение) и Avg. Disk Wright Queue Length (очередь запросов на запись).
    Значение Avg. Disk Queue Length не измеряется, а рассчитывается по закону Литтла из математической теории очередей. Согласно этому закону, количество запросов, ожидающих обработки, в среднем равняется частоте поступления запросов, умноженной на время обработки запроса. Т.е. в нашем случае Avg. Disk Queue Length = (Disk Transfers/sec) * (Avg. Disk sec/Transfer).

    Avg. Disk Queue Length приводится как один из основных счетчиков для определения загруженности дисковой подсистемы, однако для его адекватной оценки необходимо точно представлять физическую структуру системы хранения. К примеру, для одиночного жесткого диска критическим считается значение больше 2, а если диск располагается на RAID-массиве из 4-х дисков, то волноваться стоит при значении больше 4*2=8.

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

    Отслеживает количество доступной памяти в байтах для выполнения различных процессов. Низкие показатели означают нехватку памяти. Решение — увеличить память. Этот счётчик в большинстве случаев должен быть постоянно выше 5000 КВ.
    Есть смысл выставлять порог для Available Mbytes вручную из соображений:

    1. Page Splits/sec
      Количество разбиений страниц в секунду, выполненных в результате переполнения страниц индекса. Большое значение этого показателя означает, что при выполнении операций вставки и изменения данных SQL Server приходится выполнять большое количество ресурсоемких операций по разбиению страниц и переносу части существующей страницы на новое место. Таких операций по возможности следует избегать. Проблему можно попытаться решить двумя способами:
      — создать кластерный индекс для столбцов с автоприращением. В этом случае новые записи не будут помещаться внутрь страниц, уже занятых данными, а будут последовательно занимать новые страницы;
      — перестроить индексы, увеличив значение параметра Fillfactor. Этот параметр позволяет зарезервировать в страницах индексов свободное место, которое будет использоваться для размещения новых данных, без необходимости производить операции разбиения страниц.
      Zabbix: perf_counter[«\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Access Methods\Page Splits/sec»,30]
      Пример триггера: <НАЗВАНИЕ_УЗЛА:perf_counter["\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Access Methods\Page Splits/sec",30].last()>><НАЗВАНИЕ_УЗЛА:perf_counter["\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:SQL Statistics\Batch Requests/sec",30].last()>/5, уровень-информация
    2. Full Scans/sec
      Количество неограниченных операций полного сканирования в секунду. К таким операциям относятся сканирование основной таблицы и полное сканирование индекса. Стабильное повышение этого показателя может свидетельствовать о деградации системы (нехватка нужных индексов, их сильная фрагментация, неиспользование оптимизатором существующих индексов, наличие неиспользуемых индексов). Однако, стоит отметить, что полное сканирование в небольших таблицах невсегда плохо, т к если удается всю таблицу разместить в ОЗУ, то как раз быстрее будет произвести полное сканирование. Но в большинстве случаев стабильный рост показателя этого счетчика будет говорить о деградации системы. Все это применимо только для OLTP-систем. В OLAP-системах постоянные полные сканирования-это нормально.
      Zabbix: perf_counter[«\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Access Methods\Full Scans/sec»,30]
    1. Buffer Cache hit radio
      Показывает, насколько полно SQL Server может разместить данные в буфере кэша. Чем выше это значение, тем лучше, т.к. для эффективного обращения SQL сервера к страницам данных, они должны находиться в буфере кэша, и операции физического ввода-вывода (I/O) должны отсутствовать. Если наблюдается устойчивое снижение среднего значения этого счётчика, необходимо рассмотреть возможность добавления ОЗУ. Данный показатель всегда должен быть выше 90% для OLTP-систем и выше 50% для OLAP-систем.
      Zabbix: perf_counter[«\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Buffer Manager\Buffer cache hit ratio»,30]
      Примеры триггеров: <НАЗВАНИЕ_УЗЛА:perf_counter["\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Buffer Manager\Buffer cache hit ratio",30].last()>и
      <НАЗВАНИЕ_УЗЛА:perf_counter["\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Buffer Manager\Buffer cache hit ratio",30].last()>
    2. Page life expectancy
      Показывает, как долго страница будет постоянно находиться в памяти в нынешнем состоянии. Если значение постоянно падает, то это означает, что система злоупотребляет буферным пулом. Таким образом, потенциально работа памяти может вызывать проблемы, приводящие к снижению производительности. Стоит отметить, что не существует универсального показателя, ниже которого можно однозначно судить о том, что система злоупотребляет буферным пулом (показатель в 300 секунд устарел с MS SQL Server 2012).
      Zabbix: perf_counter[«\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Buffer Manager\Page life expectancy»,30]
      Пример триггера: <НАЗВАНИЕ_УЗЛА:perf_counter["\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Buffer Manager\Page life expectancy",30].last()>
    1. Process blocked
      Количество блокированных в данный момент процессов.
      Zabbix: perf_counter[«\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:General Statistics\Processes blocked»,30]
      Пример триггера: (<НАЗВАНИЕ_УЗЛА:perf_counter["\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:General Statistics\Processes blocked",30].min(2m,0)>>=0)
      and (<НАЗВАНИЕ_УЗЛА:perf_counter["\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:General Statistics\Processes blocked",30].time(0)>>=50000)
      and (<НАЗВАНИЕ_УЗЛА:perf_counter["\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:General Statistics\Processes blocked",30].time(0)><=230000), уровень-информация (здесь идет ограничение по сигнализации с 05:00 до 23:00)
    2. User Connections
      Количество пользователей, подключенных в данный момент к серверу SQL Server.
      Zabbix: perf_counter[«\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:General Statistics\User Connections»,30]
    1. Average Wait Time (ms)
      Средняя длительность ожидания (в миллисекундах) для всех запросов блокировки, при которых потребовалось ожидание. Этот счетчик показывает, сколько в среднем процессам пользователей приходится проводить в очереди, чтобы наложить на ресурс блокировку. Максимально допустимое значение этого счетчика полностью зависит от вашей задачи, какое-то среднее значение для всех приложений здесь определить сложно. Слишком высокое значение этого счетчика может означать проблемы с блокировками в вашей базе данных.
      Zabbix: perf_counter[«\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Locks(_Total)\Average Wait Time (ms)»,30]
      Пример триггера: <НАЗВАНИЕ_УЗЛА:perf_counter["\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Locks(_Total)\Average Wait Time (ms)",30].last()>>=500, уровень-информация
    2. Lock Wait Time (ms)
      Суммарное время ожидания блокировок (в миллисекундах) за последнюю секунду.
      Zabbix: perf_counter[«\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Locks(_Total)\Lock Wait Time (ms)»,30]
    3. Lock Waits/sec
      Количество случаев за последнюю секунду, когда потоку приходилось ожидать в связи с запросом блокировки.
      Zabbix: perf_counter[«\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Locks(_Total)\Lock Waits/sec»,30]
    4. Lock Timeouts/sec
      Количество повторений, когда не удается получить блокировку путем циклического обращения. Значение параметра конфигурирования SQL Server spin counter определяет количество «оборотов» потока (spins), прежде чем истечет время тайм-аута и поток перейдет в неактивное состояние.
      Zabbix: perf_counter[«\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Locks(_Total)\Lock Timeouts/sec»,30]
      Пример триггера: <НАЗВАНИЕ_УЗЛА:perf_counter["\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Locks(_Total)\Locks(_Total)\Lock Timeouts/sec",30].last()>>1000, уровень-информация
    5. Lock Requests/sec
      Количество запросов в секунду указанного типа блокировки.
      Zabbix: perf_counter[«\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Locks(_Total)\Lock Requests/sec»,30]
      Пример триггера: <НАЗВАНИЕ_УЗЛА:perf_counter["\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Locks(_Total)\Lock Requests/sec",30].last()>>500000, уровень-информация
    6. Lock Number of Deadlocks/sec
      Количество запросов блокировки в секунду, приводящих к взаимоблокировке. Наличие взаимоблокировок свидетельствует о неправильно построенных запросах, которые блокируют совместные ресурсы.
      Zabbix: perf_counter[«\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Number of Deadlocks/sec»,30]
      Пример триггера: <НАЗВАНИЕ_УЗЛА:perf_counter["\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Locks(_Total)\Number of Deadlocks/sec",30].last()>>1, уровень-высокий
    1. Memory Grants Outstanding
      Указывает общее число процессов, успешно получивших память рабочей области. При стабильном падении показателя, необходимо увеличить ОЗУ.
      Zabbix: perf_counter[«\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Memory Manager\Memory Grants Outstanding»,30]
    2. Memory Grants Pending
      Указывает общее число процессов, ожидающих предоставления памяти рабочей памяти. При стабильном росте показателя, необходимо увеличить ОЗУ.
      Zabbix: perf_counter[«\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:Memory Manager\Memory Grants Pending»,30]
    1. Batch Requests/sec
      Число пакетов команд Transact-SQL, полученных за секунду. На эту статистику влияют любые ограничения (ввод-вывод, число пользователей, размер кэша, сложность запросов и т. д.). Высокое число запросов пакетов свидетельствует о высокой пропускной способности.
      Zabbix: perf_counter[«\MSSQL$НАЗВАНИЕ_ЭКЗЕМПЛЯРА:SQL Statistics\Batch Requests/sec»,30]
    USE [ИМЯ_БАЗЫ_ДАННЫХ] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE PROCEDURE [nav].[ZabbixGetCountRequestStatus] @Status nvarchar(255) AS BEGIN /* возвращает кол-во запросов с заданным статусом */ SET NOCOUNT ON; select count(*) as [Count] from sys.dm_exec_requests ER with(readuncommitted) where [status]=@Status END 

    Далее необходимо зайти в папку, где находится Zabbix (zabbix\conf\userparams.d) и создать 2 файла с расширением ps1 (PowerShell) и написать в каждом из них следующие коды:

    Код для выполняющихся запросов

    $SQLServer = "НАЗВАНИЕ_ЭКЗЕМПЛЯРА"; $uid = "ЛОГИН"; $pwd = "ПАРОЛЬ"; $Status="running"; $connectionString = "Server = $SQLServer; Database=НАЗВАНИЕ_БД; Integrated Security = False; User Password = $pwd;"; $connection = New-Object System.Data.SqlClient.SqlConnection; $connection.ConnectionString = $connectionString; #Создаем запрос непосредственно к MSSQL / Create a request directly to MSSQL $SqlCmd = New-Object System.Data.SqlClient.SqlCommand; $SqlCmd.CommandType = [System.Data.CommandType]::StoredProcedure; $SqlCmd.CommandText = "nav.ZabbixGetCountRequestStatus"; $SqlCmd.Connection = $Connection; $paramStatus=$SqlCmd.Parameters.Add("@Status" , [System.Data.SqlDbType]::VarChar); $paramStatus.Value = $Status; $connection.Open(); $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter; $SqlAdapter.SelectCommand = $SqlCmd; $DataSet = New-Object System.Data.DataSet; $SqlAdapter.Fill($DataSet) > $null; $connection.Close(); $result = $DataSet.Tables[0].Rows[0]["Count"]; write-host $result; 

    Код для ожидающих запросов

    $SQLServer = "НАЗВАНИЕ_ЭКЗЕМПЛЯРА"; $uid = "ЛОГИН"; $pwd = "ПАРОЛЬ"; $Status="suspended"; $connectionString = "Server = $SQLServer; Database=НАЗВАНИЕ_БД; Integrated Security = False; User Password = $pwd;"; $connection = New-Object System.Data.SqlClient.SqlConnection; $connection.ConnectionString = $connectionString; #Создаем запрос непосредственно к MSSQL / Create a request directly to MSSQL $SqlCmd = New-Object System.Data.SqlClient.SqlCommand; $SqlCmd.CommandType = [System.Data.CommandType]::StoredProcedure; $SqlCmd.CommandText = "nav.ZabbixGetCountRequestStatus"; $SqlCmd.Connection = $Connection; $paramStatus=$SqlCmd.Parameters.Add("@Status" , [System.Data.SqlDbType]::VarChar); $paramStatus.Value = $Status; $connection.Open(); $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter; $SqlAdapter.SelectCommand = $SqlCmd; $DataSet = New-Object System.Data.DataSet; $SqlAdapter.Fill($DataSet) > $null; $connection.Close(); $result = $DataSet.Tables[0].Rows[0]["Count"]; write-host $result; 

    Теперь необходимо создать файл с пользовательскими параметрами и расширением .conf (или добавить строчки в существующий такой пользовательский файл, если он был создан ранее) и вставить следующие строки:
    UserParameter=НАЗВАНИЕ_ПАРАМЕТРА_КОЛИЧЕСТВО_ВЫПОЛНЯЕМЫХ_ЗАПРОСОВ,powershell -NoProfile -ExecutionPolicy Bypass -File ПОЛНЫЙ_ПУТЬ\zabbix\conf\userparams.d\НАЗВАНИЕ_ФАЙЛА_ДЛЯ_ВЫПОЛНЯЕМЫХ_ЗАПРОСОВ.ps1
    UserParameter=НАЗВАНИЕ_ПАРАМЕТРА_КОЛИЧЕСТВО_ОЖИДАЮЩИХ_ЗАПРОСОВ,powershell -NoProfile -ExecutionPolicy Bypass -File ПОЛНЫЙ_ПУТЬ\zabbix\conf\userparams.d\НАЗВАНИЕ_ФАЙЛА_ДЛЯ_ОЖИДАЮЩИХ_ЗАПРОСОВ.ps1
    После этого сохраняем файл .conf и перезапускаем агент Zabbix.
    После этого добавляем в Zabbix новых два элемента (в данном случае названия и ключ совпадают):
    НАЗВАНИЕ_ПАРАМЕТРА_КОЛИЧЕСТВО_ВЫПОЛНЯЕМЫХ_ЗАПРОСОВ
    НАЗВАНИЕ_ПАРАМЕТРА_КОЛИЧЕСТВО_ОЖИДАЮЩИХ_ЗАПРОСОВ
    Теперь можно создавать графики и триггеры на созданные пользовательские элементы данных.

    Если кол-во ожидающих запросов резко возрастает, то следующим запросом можно вывести все выполняющиеся и ожидающие запросы в данный момент времени с детализацией от куда и под каким логином выполняется запрос, текст и план запроса, а также прочие детали:

    /*Активные, готовые к выполнению и ожидающие запросы, а также те, что явно блокируют другие сеансы*/ with tbl0 as ( select ES.[session_id] ,ER.[blocking_session_id] ,ER.[request_id] ,ER.[start_time] ,ER.[status] ,ES.[status] as [status_session] ,ER.[command] ,ER.[percent_complete] ,DB_Name(coalesce(ER.[database_id], ES.[database_id])) as [DBName] ,(select top(1) [text] from sys.dm_exec_sql_text(ER.[sql_handle])) as [TSQL] ,(select top(1) [objectid] from sys.dm_exec_sql_text(ER.[sql_handle])) as [objectid] ,(select top(1) [query_plan] from sys.dm_exec_query_plan(ER.[plan_handle])) as [QueryPlan] ,ER.[wait_type] ,ES.[login_time] ,ES.[host_name] ,ES.[program_name] ,ER.[wait_time] ,ER.[last_wait_type] ,ER.[wait_resource] ,ER.[open_transaction_count] ,ER.[open_resultset_count] ,ER.[transaction_id] ,ER.[context_info] ,ER.[estimated_completion_time] ,ER.[cpu_time] ,ER.[total_elapsed_time] ,ER.[scheduler_id] ,ER.[task_address] ,ER.[reads] ,ER.[writes] ,ER.[logical_reads] ,ER.[text_size] ,ER.[language] ,ER.[date_format] ,ER.[date_first] ,ER.[quoted_identifier] ,ER.[arithabort] ,ER.[ansi_null_dflt_on] ,ER.[ansi_defaults] ,ER.[ansi_warnings] ,ER.[ansi_padding] ,ER.[ansi_nulls] ,ER.[concat_null_yields_null] ,ER.[transaction_isolation_level] ,ER.[lock_timeout] ,ER.[deadlock_priority] ,ER.[row_count] ,ER.[prev_error] ,ER.[nest_level] ,ER.[granted_query_memory] ,ER.[executing_managed_code] ,ER.[group_id] ,ER.[query_hash] ,ER.[query_plan_hash] ,EC.[most_recent_session_id] ,EC.[connect_time] ,EC.[net_transport] ,EC.[protocol_type] ,EC.[protocol_version] ,EC.[endpoint_id] ,EC.[encrypt_option] ,EC.[auth_scheme] ,EC.[node_affinity] ,EC.[num_reads] ,EC.[num_writes] ,EC.[last_read] ,EC.[last_write] ,EC.[net_packet_size] ,EC.[client_net_address] ,EC.[client_tcp_port] ,EC.[local_net_address] ,EC.[local_tcp_port] ,EC.[parent_connection_id] ,EC.[most_recent_sql_handle] ,ES.[host_process_id] ,ES.[client_version] ,ES.[client_interface_name] ,ES.[security_id] ,ES.[login_name] ,ES.[nt_domain] ,ES.[nt_user_name] ,ES.[memory_usage] ,ES.[total_scheduled_time] ,ES.[last_request_start_time] ,ES.[last_request_end_time] ,ES.[is_user_process] ,ES.[original_security_id] ,ES.[original_login_name] ,ES.[last_successful_logon] ,ES.[last_unsuccessful_logon] ,ES.[unsuccessful_logons] ,ES.[authenticating_database_id] ,ER.[sql_handle] ,ER.[statement_start_offset] ,ER.[statement_end_offset] ,ER.[plan_handle] ,ER.[dop] ,coalesce(ER.[database_id], ES.[database_id]) as [database_id] ,ER.[user_id] ,ER.[connection_id] from sys.dm_exec_requests ER with(readuncommitted) right join sys.dm_exec_sessions ES with(readuncommitted) on ES.session_id = ER.session_id left join sys.dm_exec_connections EC with(readuncommitted) on EC.session_id = ES.session_id ) , tbl as ( select [session_id] ,[blocking_session_id] ,[request_id] ,[start_time] ,[status] ,[status_session] ,[command] ,[percent_complete] ,[DBName] ,OBJECT_name([objectid], [database_id]) as [object] ,[TSQL] ,[QueryPlan] ,[wait_type] ,[login_time] ,[host_name] ,[program_name] ,[wait_time] ,[last_wait_type] ,[wait_resource] ,[open_transaction_count] ,[open_resultset_count] ,[transaction_id] ,[context_info] ,[estimated_completion_time] ,[cpu_time] ,[total_elapsed_time] ,[scheduler_id] ,[task_address] ,[reads] ,[writes] ,[logical_reads] ,[text_size] ,[language] ,[date_format] ,[date_first] ,[quoted_identifier] ,[arithabort] ,[ansi_null_dflt_on] ,[ansi_defaults] ,[ansi_warnings] ,[ansi_padding] ,[ansi_nulls] ,[concat_null_yields_null] ,[transaction_isolation_level] ,[lock_timeout] ,[deadlock_priority] ,[row_count] ,[prev_error] ,[nest_level] ,[granted_query_memory] ,[executing_managed_code] ,[group_id] ,[query_hash] ,[query_plan_hash] ,[most_recent_session_id] ,[connect_time] ,[net_transport] ,[protocol_type] ,[protocol_version] ,[endpoint_id] ,[encrypt_option] ,[auth_scheme] ,[node_affinity] ,[num_reads] ,[num_writes] ,[last_read] ,[last_write] ,[net_packet_size] ,[client_net_address] ,[client_tcp_port] ,[local_net_address] ,[local_tcp_port] ,[parent_connection_id] ,[most_recent_sql_handle] ,[host_process_id] ,[client_version] ,[client_interface_name] ,[security_id] ,[login_name] ,[nt_domain] ,[nt_user_name] ,[memory_usage] ,[total_scheduled_time] ,[last_request_start_time] ,[last_request_end_time] ,[is_user_process] ,[original_security_id] ,[original_login_name] ,[last_successful_logon] ,[last_unsuccessful_logon] ,[unsuccessful_logons] ,[authenticating_database_id] ,[sql_handle] ,[statement_start_offset] ,[statement_end_offset] ,[plan_handle] ,[dop] ,[database_id] ,[user_id] ,[connection_id] from tbl0 where [status] in ('suspended', 'running', 'runnable') ) , tbl_group as ( select [blocking_session_id] from tbl where [blocking_session_id]<>0 group by [blocking_session_id] ) , tbl_res_rec as ( select [session_id] ,[blocking_session_id] ,[request_id] ,[start_time] ,[status] ,[status_session] ,[command] ,[percent_complete] ,[DBName] ,[object] ,[TSQL] ,[QueryPlan] ,[wait_type] ,[login_time] ,[host_name] ,[program_name] ,[wait_time] ,[last_wait_type] ,[wait_resource] ,[open_transaction_count] ,[open_resultset_count] ,[transaction_id] ,[context_info] ,[estimated_completion_time] ,[cpu_time] ,[total_elapsed_time] ,[scheduler_id] ,[task_address] ,[reads] ,[writes] ,[logical_reads] ,[text_size] ,[language] ,[date_format] ,[date_first] ,[quoted_identifier] ,[arithabort] ,[ansi_null_dflt_on] ,[ansi_defaults] ,[ansi_warnings] ,[ansi_padding] ,[ansi_nulls] ,[concat_null_yields_null] ,[transaction_isolation_level] ,[lock_timeout] ,[deadlock_priority] ,[row_count] ,[prev_error] ,[nest_level] ,[granted_query_memory] ,[executing_managed_code] ,[group_id] ,[query_hash] ,[query_plan_hash] ,[most_recent_session_id] ,[connect_time] ,[net_transport] ,[protocol_type] ,[protocol_version] ,[endpoint_id] ,[encrypt_option] ,[auth_scheme] ,[node_affinity] ,[num_reads] ,[num_writes] ,[last_read] ,[last_write] ,[net_packet_size] ,[client_net_address] ,[client_tcp_port] ,[local_net_address] ,[local_tcp_port] ,[parent_connection_id] ,[most_recent_sql_handle] ,[host_process_id] ,[client_version] ,[client_interface_name] ,[security_id] ,[login_name] ,[nt_domain] ,[nt_user_name] ,[memory_usage] ,[total_scheduled_time] ,[last_request_start_time] ,[last_request_end_time] ,[is_user_process] ,[original_security_id] ,[original_login_name] ,[last_successful_logon] ,[last_unsuccessful_logon] ,[unsuccessful_logons] ,[authenticating_database_id] ,[sql_handle] ,[statement_start_offset] ,[statement_end_offset] ,[plan_handle] ,[dop] ,[database_id] ,[user_id] ,[connection_id] , 0 as [is_blocking_other_session] from tbl union all select tbl0.[session_id] ,tbl0.[blocking_session_id] ,tbl0.[request_id] ,tbl0.[start_time] ,tbl0.[status] ,tbl0.[status_session] ,tbl0.[command] ,tbl0.[percent_complete] ,tbl0.[DBName] ,OBJECT_name(tbl0.[objectid], tbl0.[database_id]) as [object] ,tbl0.[TSQL] ,tbl0.[QueryPlan] ,tbl0.[wait_type] ,tbl0.[login_time] ,tbl0.[host_name] ,tbl0.[program_name] ,tbl0.[wait_time] ,tbl0.[last_wait_type] ,tbl0.[wait_resource] ,tbl0.[open_transaction_count] ,tbl0.[open_resultset_count] ,tbl0.[transaction_id] ,tbl0.[context_info] ,tbl0.[estimated_completion_time] ,tbl0.[cpu_time] ,tbl0.[total_elapsed_time] ,tbl0.[scheduler_id] ,tbl0.[task_address] ,tbl0.[reads] ,tbl0.[writes] ,tbl0.[logical_reads] ,tbl0.[text_size] ,tbl0.[language] ,tbl0.[date_format] ,tbl0.[date_first] ,tbl0.[quoted_identifier] ,tbl0.[arithabort] ,tbl0.[ansi_null_dflt_on] ,tbl0.[ansi_defaults] ,tbl0.[ansi_warnings] ,tbl0.[ansi_padding] ,tbl0.[ansi_nulls] ,tbl0.[concat_null_yields_null] ,tbl0.[transaction_isolation_level] ,tbl0.[lock_timeout] ,tbl0.[deadlock_priority] ,tbl0.[row_count] ,tbl0.[prev_error] ,tbl0.[nest_level] ,tbl0.[granted_query_memory] ,tbl0.[executing_managed_code] ,tbl0.[group_id] ,tbl0.[query_hash] ,tbl0.[query_plan_hash] ,tbl0.[most_recent_session_id] ,tbl0.[connect_time] ,tbl0.[net_transport] ,tbl0.[protocol_type] ,tbl0.[protocol_version] ,tbl0.[endpoint_id] ,tbl0.[encrypt_option] ,tbl0.[auth_scheme] ,tbl0.[node_affinity] ,tbl0.[num_reads] ,tbl0.[num_writes] ,tbl0.[last_read] ,tbl0.[last_write] ,tbl0.[net_packet_size] ,tbl0.[client_net_address] ,tbl0.[client_tcp_port] ,tbl0.[local_net_address] ,tbl0.[local_tcp_port] ,tbl0.[parent_connection_id] ,tbl0.[most_recent_sql_handle] ,tbl0.[host_process_id] ,tbl0.[client_version] ,tbl0.[client_interface_name] ,tbl0.[security_id] ,tbl0.[login_name] ,tbl0.[nt_domain] ,tbl0.[nt_user_name] ,tbl0.[memory_usage] ,tbl0.[total_scheduled_time] ,tbl0.[last_request_start_time] ,tbl0.[last_request_end_time] ,tbl0.[is_user_process] ,tbl0.[original_security_id] ,tbl0.[original_login_name] ,tbl0.[last_successful_logon] ,tbl0.[last_unsuccessful_logon] ,tbl0.[unsuccessful_logons] ,tbl0.[authenticating_database_id] ,tbl0.[sql_handle] ,tbl0.[statement_start_offset] ,tbl0.[statement_end_offset] ,tbl0.[plan_handle] ,tbl0.[dop] ,tbl0.[database_id] ,tbl0.[user_id] ,tbl0.[connection_id] , 1 as [is_blocking_other_session] from tbl_group as tg inner join tbl0 on tg.blocking_session_id=tbl0.session_id ) ,tbl_res_rec_g as ( select [plan_handle], [sql_handle], cast([start_time] as date) as [start_time] from tbl_res_rec group by [plan_handle], [sql_handle], cast([start_time] as date) ) ,tbl_rec_stat_g as ( select qs.[plan_handle] ,qs.[sql_handle] --,cast(qs.[last_execution_time] as date) as [last_execution_time] ,min(qs.[creation_time]) as [creation_time] ,max(qs.[execution_count]) as [execution_count] ,max(qs.[total_worker_time]) as [total_worker_time] ,min(qs.[last_worker_time]) as [min_last_worker_time] ,max(qs.[last_worker_time]) as [max_last_worker_time] ,min(qs.[min_worker_time]) as [min_worker_time] ,max(qs.[max_worker_time]) as [max_worker_time] ,max(qs.[total_physical_reads]) as [total_physical_reads] ,min(qs.[last_physical_reads]) as [min_last_physical_reads] ,max(qs.[last_physical_reads]) as [max_last_physical_reads] ,min(qs.[min_physical_reads]) as [min_physical_reads] ,max(qs.[max_physical_reads]) as [max_physical_reads] ,max(qs.[total_logical_writes]) as [total_logical_writes] ,min(qs.[last_logical_writes]) as [min_last_logical_writes] ,max(qs.[last_logical_writes]) as [max_last_logical_writes] ,min(qs.[min_logical_writes]) as [min_logical_writes] ,max(qs.[max_logical_writes]) as [max_logical_writes] ,max(qs.[total_logical_reads]) as [total_logical_reads] ,min(qs.[last_logical_reads]) as [min_last_logical_reads] ,max(qs.[last_logical_reads]) as [max_last_logical_reads] ,min(qs.[min_logical_reads]) as [min_logical_reads] ,max(qs.[max_logical_reads]) as [max_logical_reads] ,max(qs.[total_clr_time]) as [total_clr_time] ,min(qs.[last_clr_time]) as [min_last_clr_time] ,max(qs.[last_clr_time]) as [max_last_clr_time] ,min(qs.[min_clr_time]) as [min_clr_time] ,max(qs.[max_clr_time]) as [max_clr_time] ,max(qs.[total_elapsed_time]) as [total_elapsed_time] ,min(qs.[last_elapsed_time]) as [min_last_elapsed_time] ,max(qs.[last_elapsed_time]) as [max_last_elapsed_time] ,min(qs.[min_elapsed_time]) as [min_elapsed_time] ,max(qs.[max_elapsed_time]) as [max_elapsed_time] ,max(qs.[total_rows]) as [total_rows] ,min(qs.[last_rows]) as [min_last_rows] ,max(qs.[last_rows]) as [max_last_rows] ,min(qs.[min_rows]) as [min_rows] ,max(qs.[max_rows]) as [max_rows] ,max(qs.[total_dop]) as [total_dop] ,min(qs.[last_dop]) as [min_last_dop] ,max(qs.[last_dop]) as [max_last_dop] ,min(qs.[min_dop]) as [min_dop] ,max(qs.[max_dop]) as [max_dop] ,max(qs.[total_grant_kb]) as [total_grant_kb] ,min(qs.[last_grant_kb]) as [min_last_grant_kb] ,max(qs.[last_grant_kb]) as [max_last_grant_kb] ,min(qs.[min_grant_kb]) as [min_grant_kb] ,max(qs.[max_grant_kb]) as [max_grant_kb] ,max(qs.[total_used_grant_kb]) as [total_used_grant_kb] ,min(qs.[last_used_grant_kb]) as [min_last_used_grant_kb] ,max(qs.[last_used_grant_kb]) as [max_last_used_grant_kb] ,min(qs.[min_used_grant_kb]) as [min_used_grant_kb] ,max(qs.[max_used_grant_kb]) as [max_used_grant_kb] ,max(qs.[total_ideal_grant_kb]) as [total_ideal_grant_kb] ,min(qs.[last_ideal_grant_kb]) as [min_last_ideal_grant_kb] ,max(qs.[last_ideal_grant_kb]) as [max_last_ideal_grant_kb] ,min(qs.[min_ideal_grant_kb]) as [min_ideal_grant_kb] ,max(qs.[max_ideal_grant_kb]) as [max_ideal_grant_kb] ,max(qs.[total_reserved_threads]) as [total_reserved_threads] ,min(qs.[last_reserved_threads]) as [min_last_reserved_threads] ,max(qs.[last_reserved_threads]) as [max_last_reserved_threads] ,min(qs.[min_reserved_threads]) as [min_reserved_threads] ,max(qs.[max_reserved_threads]) as [max_reserved_threads] ,max(qs.[total_used_threads]) as [total_used_threads] ,min(qs.[last_used_threads]) as [min_last_used_threads] ,max(qs.[last_used_threads]) as [max_last_used_threads] ,min(qs.[min_used_threads]) as [min_used_threads] ,max(qs.[max_used_threads]) as [max_used_threads] from tbl_res_rec_g as t inner join sys.dm_exec_query_stats as qs with(readuncommitted) on t.[plan_handle]=qs.[plan_handle] and t.[sql_handle]=qs.[sql_handle] and t.[start_time]=cast(qs.[last_execution_time] as date) group by qs.[plan_handle] ,qs.[sql_handle] --,qs.[last_execution_time] ) select t.[session_id] --Сессия ,t.[blocking_session_id] --Сессия, которая явно блокирует сессию [session_id] ,t.[request_id] --Идентификатор запроса. Уникален в контексте сеанса ,t.[start_time] --Метка времени поступления запроса ,DateDiff(second, t.[start_time], GetDate()) as [date_diffSec] --Сколько в сек прошло времени от момента поступления запроса ,t.[status] --Состояние запроса ,t.[status_session] --Состояние сессии ,t.[command] --Тип выполняемой в данный момент команды , COALESCE( CAST(NULLIF(t.[total_elapsed_time] / 1000, 0) as BIGINT) ,CASE WHEN (t.[status_session] <> 'running' and isnull(t.[status], '') <> 'running') THEN DATEDIFF(ss,0,getdate() - nullif(t.[last_request_end_time], '1900-01-01T00:00:00.000')) END ) as [total_time, sec] --Время всей работы запроса в сек , CAST(NULLIF((CAST(t.[total_elapsed_time] as BIGINT) - CAST(t.[wait_time] AS BIGINT)) / 1000, 0 ) as bigint) as [work_time, sec] --Время работы запроса в сек без учета времени ожиданий , CASE WHEN (t.[status_session] <> 'running' AND ISNULL(t.[status],'') <> 'running') THEN DATEDIFF(ss,0,getdate() - nullif(t.[last_request_end_time], '1900-01-01T00:00:00.000')) END as [sleep_time, sec] --Время сна в сек , NULLIF( CAST((t.[logical_reads] + t.[writes]) * 8 / 1024 as numeric(38,2)), 0) as [IO, MB] --операций чтения и записи в МБ , CASE t.transaction_isolation_level WHEN 0 THEN 'Unspecified' WHEN 1 THEN 'ReadUncommited' WHEN 2 THEN 'ReadCommited' WHEN 3 THEN 'Repetable' WHEN 4 THEN 'Serializable' WHEN 5 THEN 'Snapshot' END as [transaction_isolation_level_desc] --уровень изоляции транзакции (расшифровка) ,t.[percent_complete] --Процент завершения работы для следующих команд ,t.[DBName] --БД ,t.[object] --Объект , SUBSTRING( t.[TSQL] , t.[statement_start_offset]/2+1 , ( CASE WHEN ((t.[statement_start_offset]<0) OR (t.[statement_end_offset]<0)) THEN DATALENGTH (t.[TSQL]) ELSE t.[statement_end_offset] END - t.[statement_start_offset] )/2 +1 ) as [CURRENT_REQUEST] --Текущий выполняемый запрос в пакете ,t.[TSQL] --Запрос всего пакета ,t.[QueryPlan] --План всего пакета ,t.[wait_type] --Если запрос в настоящий момент блокирован, в столбце содержится тип ожидания (sys.dm_os_wait_stats) ,t.[login_time] --Время подключения сеанса ,t.[host_name] --Имя клиентской рабочей станции, указанное в сеансе. Для внутреннего сеанса это значение равно NULL ,t.[program_name] --Имя клиентской программы, которая инициировала сеанс. Для внутреннего сеанса это значение равно NULL ,cast(t.[wait_time]/1000 as decimal(18,3)) as [wait_timeSec] --Если запрос в настоящий момент блокирован, в столбце содержится продолжительность текущего ожидания (в секундах) ,t.[wait_time] --Если запрос в настоящий момент блокирован, в столбце содержится продолжительность текущего ожидания (в миллисекундах) ,t.[last_wait_type] --Если запрос был блокирован ранее, в столбце содержится тип последнего ожидания ,t.[wait_resource] --Если запрос в настоящий момент блокирован, в столбце указан ресурс, освобождения которого ожидает запрос ,t.[open_transaction_count] --Число транзакций, открытых для данного запроса ,t.[open_resultset_count] --Число результирующих наборов, открытых для данного запроса ,t.[transaction_id] --Идентификатор транзакции, в которой выполняется запрос ,t.[context_info] --Значение CONTEXT_INFO сеанса ,cast(t.[estimated_completion_time]/1000 as decimal(18,3)) as [estimated_completion_timeSec] --Только для внутреннего использования. Не допускает значение NULL ,t.[estimated_completion_time] --Только для внутреннего использования. Не допускает значение NULL ,cast(t.[cpu_time]/1000 as decimal(18,3)) as [cpu_timeSec] --Время ЦП (в секундах), затраченное на выполнение запроса ,t.[cpu_time] --Время ЦП (в миллисекундах), затраченное на выполнение запроса ,cast(t.[total_elapsed_time]/1000 as decimal(18,3)) as [total_elapsed_timeSec] --Общее время, истекшее с момента поступления запроса (в секундах) ,t.[total_elapsed_time] --Общее время, истекшее с момента поступления запроса (в миллисекундах) ,t.[scheduler_id] --Идентификатор планировщика, который планирует данный запрос ,t.[task_address] --Адрес блока памяти, выделенного для задачи, связанной с этим запросом ,t.[reads] --Число операций чтения, выполненных данным запросом ,t.[writes] --Число операций записи, выполненных данным запросом ,t.[logical_reads] --Число логических операций чтения, выполненных данным запросом ,t.[text_size] --Установка параметра TEXTSIZE для данного запроса ,t.[language] --Установка языка для данного запроса ,t.[date_format] --Установка параметра DATEFORMAT для данного запроса ,t.[date_first] --Установка параметра DATEFIRST для данного запроса ,t.[quoted_identifier] --1 = Параметр QUOTED_IDENTIFIER для запроса включен (ON). В противном случае — 0 ,t.[arithabort] --1 = Параметр ARITHABORT для запроса включен (ON). В противном случае — 0 ,t.[ansi_null_dflt_on] --1 = Параметр ANSI_NULL_DFLT_ON для запроса включен (ON). В противном случае — 0 ,t.[ansi_defaults] --1 = Параметр ANSI_DEFAULTS для запроса включен (ON). В противном случае — 0 ,t.[ansi_warnings] --1 = Параметр ANSI_WARNINGS для запроса включен (ON). В противном случае — 0 ,t.[ansi_padding] --1 = Параметр ANSI_PADDING для запроса включен (ON) ,t.[ansi_nulls] --1 = Параметр ANSI_NULLS для запроса включен (ON). В противном случае — 0 ,t.[concat_null_yields_null] --1 = Параметр CONCAT_NULL_YIELDS_NULL для запроса включен (ON). В противном случае — 0 ,t.[transaction_isolation_level] --Уровень изоляции, с которым создана транзакция для данного запроса ,cast(t.[lock_timeout]/1000 as decimal(18,3)) as [lock_timeoutSec] --Время ожидания блокировки для данного запроса (в секундах) ,t.[lock_timeout] --Время ожидания блокировки для данного запроса (в миллисекундах) ,t.[deadlock_priority] --Значение параметра DEADLOCK_PRIORITY для данного запроса ,t.[row_count] --Число строк, возвращенных клиенту по данному запросу ,t.[prev_error] --Последняя ошибка, происшедшая при выполнении запроса ,t.[nest_level] --Текущий уровень вложенности кода, выполняемого для данного запроса ,t.[granted_query_memory] --Число страниц, выделенных для выполнения поступившего запроса (1 страница-это примерно 8 КБ) ,t.[executing_managed_code] --Указывает, выполняет ли данный запрос в настоящее время код объекта среды CLR (например, процедуры, типа или триггера). --Этот флаг установлен в течение всего времени, когда объект среды CLR находится в стеке, даже когда из среды вызывается код Transact-SQL ,t.[group_id] --Идентификатор группы рабочей нагрузки, которой принадлежит этот запрос ,t.[query_hash] --Двоичное хэш-значение рассчитывается для запроса и используется для идентификации запросов с аналогичной логикой. --Можно использовать хэш запроса для определения использования статистических ресурсов для запросов, которые отличаются только своими литеральными значениями ,t.[query_plan_hash] --Двоичное хэш-значение рассчитывается для плана выполнения запроса и используется для идентификации аналогичных планов выполнения запросов. --Можно использовать хэш плана запроса для нахождения совокупной стоимости запросов со схожими планами выполнения ,t.[most_recent_session_id] --Представляет собой идентификатор сеанса самого последнего запроса, связанного с данным соединением ,t.[connect_time] --Отметка времени установления соединения ,t.[net_transport] --Содержит описание физического транспортного протокола, используемого данным соединением ,t.[protocol_type] --Указывает тип протокола передачи полезных данных ,t.[protocol_version] --Версия протокола доступа к данным, связанного с данным соединением ,t.[endpoint_id] --Идентификатор, описывающий тип соединения. Этот идентификатор endpoint_id может использоваться для запросов к представлению sys.endpoints ,t.[encrypt_option] --Логическое значение, указывающее, разрешено ли шифрование для данного соединения ,t.[auth_scheme] --Указывает схему проверки подлинности (SQL Server или Windows), используемую с данным соединением ,t.[node_affinity] --Идентифицирует узел памяти, которому соответствует данное соединение ,t.[num_reads] --Число пакетов, принятых посредством данного соединения ,t.[num_writes] --Число пакетов, переданных посредством данного соединения ,t.[last_read] --Отметка времени о последнем полученном пакете данных ,t.[last_write] --Отметка времени о последнем отправленном пакете данных ,t.[net_packet_size] --Размер сетевого пакета, используемый для передачи данных ,t.[client_net_address] --Сетевой адрес удаленного клиента ,t.[client_tcp_port] --Номер порта на клиентском компьютере, который используется при осуществлении соединения ,t.[local_net_address] --IP-адрес сервера, с которым установлено данное соединение. Доступен только для соединений, которые в качестве транспорта данных используют протокол TCP ,t.[local_tcp_port] --TCP-порт сервера, если соединение использует протокол TCP ,t.[parent_connection_id] --Идентифицирует первичное соединение, используемое в сеансе MARS ,t.[most_recent_sql_handle] --Дескриптор последнего запроса SQL, выполненного с помощью данного соединения. Постоянно проводится синхронизация между столбцом most_recent_sql_handle и столбцом most_recent_session_id ,t.[host_process_id] --Идентификатор процесса клиентской программы, которая инициировала сеанс. Для внутреннего сеанса это значение равно NULL ,t.[client_version] --Версия TDS-протокола интерфейса, который используется клиентом для подключения к серверу. Для внутреннего сеанса это значение равно NULL ,t.[client_interface_name] --Имя библиотеки или драйвер, используемый клиентом для обмена данными с сервером. Для внутреннего сеанса это значение равно NULL ,t.[security_id] --Идентификатор безопасности Microsoft Windows, связанный с именем входа ,t.[login_name] --SQL Server Имя входа, под которой выполняется текущий сеанс. --Чтобы узнать первоначальное имя входа, с помощью которого был создан сеанс, см. параметр original_login_name. --Может быть SQL Server проверка подлинности имени входа или имени пользователя домена, прошедшего проверку подлинности Windows ,t.[nt_domain] --Домен Windows для клиента, если во время сеанса применяется проверка подлинности Windows или доверительное соединение. --Для внутренних сеансов и пользователей, не принадлежащих к домену, это значение равно NULL ,t.[nt_user_name] --Имя пользователя Windows для клиента, если во время сеанса используется проверка подлинности Windows или доверительное соединение. --Для внутренних сеансов и пользователей, не принадлежащих к домену, это значение равно NULL ,t.[memory_usage] --Количество 8-килобайтовых страниц памяти, используемых данным сеансом ,t.[total_scheduled_time] --Общее время, назначенное данному сеансу (включая его вложенные запросы) для исполнения, в миллисекундах ,t.[last_request_start_time] --Время, когда начался последний запрос данного сеанса. Это может быть запрос, выполняющийся в данный момент ,t.[last_request_end_time] --Время завершения последнего запроса в рамках данного сеанса ,t.[is_user_process] --0, если сеанс является системным. В противном случае значение равно 1 ,t.[original_security_id] --Microsoft Идентификатор безопасности Windows, связанный с параметром original_login_name ,t.[original_login_name] --SQL Server Имя входа, которую использует клиент создал данный сеанс. --Это может быть имя входа SQL Server, прошедшее проверку подлинности, имя пользователя домена Windows, --прошедшее проверку подлинности, или пользователь автономной базы данных. --Обратите внимание, что после первоначального соединения для сеанса может быть выполнено много неявных или явных переключений контекста. --Например если EXECUTE AS используется ,t.[last_successful_logon] --Время последнего успешного входа в систему для имени original_login_name до запуска текущего сеанса ,t.[last_unsuccessful_logon] --Время последнего неуспешного входа в систему для имени original_login_name до запуска текущего сеанса ,t.[unsuccessful_logons] --Число неуспешных попыток входа в систему для имени original_login_name между временем last_successful_logon и временем login_time ,t.[authenticating_database_id] --Идентификатор базы данных, выполняющей проверку подлинности участника. --Для имен входа это значение будет равно 0. --Для пользователей автономной базы данных это значение будет содержать идентификатор автономной базы данных ,t.[sql_handle] --Хэш-карта текста SQL-запроса ,t.[statement_start_offset] --Количество символов в выполняемом в настоящий момент пакете или хранимой процедуре, в которой запущена текущая инструкция. --Может применяться вместе с функциями динамического управления sql_handle, statement_end_offset и sys.dm_exec_sql_text --для извлечения исполняемой в настоящий момент инструкции по запросу ,t.[statement_end_offset] --Количество символов в выполняемом в настоящий момент пакете или хранимой процедуре, в которой завершилась текущая инструкция. --Может применяться вместе с функциями динамического управления sql_handle, statement_end_offset и sys.dm_exec_sql_text --для извлечения исполняемой в настоящий момент инструкции по запросу ,t.[plan_handle] --Хэш-карта плана выполнения SQL ,t.[database_id] --Идентификатор базы данных, к которой выполняется запрос ,t.[user_id] --Идентификатор пользователя, отправившего данный запрос ,t.[connection_id] --Идентификатор соединения, по которому поступил запрос ,t.[is_blocking_other_session] --1-сессия явно блокирует другие сессии, 0-сессия явно не блокирует другие сессии ,coalesce(t.[dop], mg.[dop]) as [dop] --Степень параллелизма запроса ,mg.[request_time] --Дата и время обращения запроса за предоставлением памяти ,mg.[grant_time] --Дата и время, когда запросу была предоставлена память. Возвращает значение NULL, если память еще не была предоставлена ,mg.[requested_memory_kb] --Общий объем запрошенной памяти в килобайтах ,mg.[granted_memory_kb] --Общий объем фактически предоставленной памяти в килобайтах. --Может быть значение NULL, если память еще не была предоставлена. --Обычно это значение должно быть одинаковым с requested_memory_kb. --Для создания индекса сервер может разрешить дополнительное предоставление по требованию памяти, --объем которой выходит за рамки изначально предоставленной памяти ,mg.[required_memory_kb] --Минимальный объем памяти в килобайтах (КБ), необходимый для выполнения данного запроса. --Значение requested_memory_kb равно этому объему или больше его ,mg.[used_memory_kb] --Используемый в данный момент объем физической памяти (в килобайтах) ,mg.[max_used_memory_kb] --Максимальный объем используемой до данного момента физической памяти в килобайтах ,mg.[query_cost] --Ожидаемая стоимость запроса ,mg.[timeout_sec] --Время ожидания данного запроса в секундах до отказа от обращения за предоставлением памяти ,mg.[resource_semaphore_id] --Неуникальный идентификатор семафора ресурса, которого ожидает данный запрос ,mg.[queue_id] --Идентификатор ожидающей очереди, в которой данный запрос ожидает предоставления памяти. --Значение NULL, если память уже предоставлена ,mg.[wait_order] --Последовательный порядок ожидающих запросов в указанной очереди queue_id. --Это значение может изменяться для заданного запроса, если другие запросы отказываются от предоставления памяти или получают ее. --Значение NULL, если память уже предоставлена ,mg.[is_next_candidate] --Является следующим кандидатом на предоставление памяти (1 = да, 0 = нет, NULL = память уже предоставлена) ,mg.[wait_time_ms] --Время ожидания в миллисекундах. Значение NULL, если память уже предоставлена ,mg.[pool_id] --Идентификатор пула ресурсов, к которому принадлежит данная группа рабочей нагрузки ,mg.[is_small] --Значение 1 означает, что для данной операции предоставления памяти используется малый семафор ресурса. --Значение 0 означает использование обычного семафора ,mg.[ideal_memory_kb] --Объем, в килобайтах (КБ), предоставленной памяти, необходимый для размещения всех данных в физической памяти. --Основывается на оценке количества элементов ,mg.[reserved_worker_count] --Число рабочих процессов, зарезервированной с помощью параллельных запросов, а также число основных рабочих процессов, используемых всеми запросами ,mg.[used_worker_count] --Число рабочих процессов, используемых параллельных запросов ,mg.[max_used_worker_count] --. ,mg.[reserved_node_bitmap] --. ,pl.[bucketid] --Идентификатор сегмента хэша, в который кэшируется запись. --Значение указывает диапазон от 0 до значения размера хэш-таблицы для типа кэша. --Для кэшей SQL Plans и Object Plans размер хэш-таблицы может достигать 10007 на 32-разрядных версиях систем и 40009 — на 64-разрядных. --Для кэша Bound Trees размер хэш-таблицы может достигать 1009 на 32-разрядных версиях систем и 4001 на 64-разрядных. --Для кэша расширенных хранимых процедур размер хэш-таблицы может достигать 127 на 32-разрядных и 64-разрядных версиях систем ,pl.[refcounts] --Число объектов кэша, ссылающихся на данный объект кэша. --Значение refcounts для записи должно быть не меньше 1, чтобы размещаться в кэше ,pl.[usecounts] --Количество повторений поиска объекта кэша. --Остается без увеличения, если параметризованные запросы обнаруживают план в кэше. --Может быть увеличен несколько раз при использовании инструкции showplan ,pl.[size_in_bytes] --Число байтов, занимаемых объектом кэша ,pl.[memory_object_address] --Адрес памяти кэшированной записи. --Это значение можно использовать с представлением sys.dm_os_memory_objects, --чтобы проанализировать распределение памяти кэшированного плана, --и с представлением sys.dm_os_memory_cache_entries для определения затрат на кэширование записи ,pl.[cacheobjtype] --Тип объекта в кэше. Значение может быть одним из следующих ,pl.[objtype] --Тип объекта. Значение может быть одним из следующих ,pl.[parent_plan_handle] --Родительский план --данные из sys.dm_exec_query_stats брались за сутки, в которых была пара (запрос, план) ,qs.[creation_time] --Время компиляции плана ,qs.[execution_count] --Количество выполнений плана с момента последней компиляции ,qs.[total_worker_time] --Общее время ЦП, затраченное на выполнение плана с момента компиляции, в микросекундах (но с точностью до миллисекунды) ,qs.[min_last_worker_time] --Минимальное время ЦП, затраченное на последнее выполнение плана, в микросекундах (но с точностью до миллисекунды) ,qs.[max_last_worker_time] --Максимальное время ЦП, затраченное на последнее выполнение плана, в микросекундах (но с точностью до миллисекунды) ,qs.[min_worker_time] --Минимальное время ЦП, когда-либо затраченное на выполнение плана, в микросекундах (но с точностью до миллисекунды) ,qs.[max_worker_time] --Максимальное время ЦП, когда-либо затраченное на выполнение плана, в микросекундах (но с точностью до миллисекунды) ,qs.[total_physical_reads] --Общее количество операций физического считывания при выполнении плана с момента его компиляции. --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы ,qs.[min_last_physical_reads] --Минимальное количество операций физического считывания за время последнего выполнения плана. --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы ,qs.[max_last_physical_reads] --Максимальное количество операций физического считывания за время последнего выполнения плана. --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы ,qs.[min_physical_reads] --Минимальное количество операций физического считывания за одно выполнение плана. --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы ,qs.[max_physical_reads] --Максимальное количество операций физического считывания за одно выполнение плана. --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы ,qs.[total_logical_writes] --Общее количество операций логической записи при выполнении плана с момента его компиляции. --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы ,qs.[min_last_logical_writes] --Минимальное количество страниц в буферном пуле, загрязненных во время последнего выполнения плана. --Если страница уже является «грязной» (т. е. измененной), операции записи не учитываются. --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы ,qs.[max_last_logical_writes] --Максимальное количество страниц в буферном пуле, загрязненных во время последнего выполнения плана. --Если страница уже является «грязной» (т. е. измененной), операции записи не учитываются. --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы ,qs.[min_logical_writes] --Минимальное количество операций логической записи за одно выполнение плана. --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы ,qs.[max_logical_writes] --Максимальное количество операций логической записи за одно выполнение плана. --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы ,qs.[total_logical_reads] --Общее количество операций логического считывания при выполнении плана с момента его компиляции. --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы ,qs.[min_last_logical_reads] --Минимальное количество операций логического считывания за время последнего выполнения плана. --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы ,qs.[max_last_logical_reads] --Максимальное количество операций логического считывания за время последнего выполнения плана. --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы ,qs.[min_logical_reads] --Минимальное количество операций логического считывания за одно выполнение плана. --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы ,qs.[max_logical_reads] --Максимальное количество операций логического считывания за одно выполнение плана. --Значение всегда равно 0 при запросе оптимизированной для памяти таблицы ,qs.[total_clr_time] --Время, в микросекундах (но с точностью до миллисекунды), --внутри Microsoft .NET Framework общеязыковая среда выполнения (CLR) объекты при выполнении плана с момента его компиляции. --Объекты среды CLR могут быть хранимыми процедурами, функциями, триггерами, типами и статистическими выражениями ,qs.[min_last_clr_time] --Минимальное время, в микросекундах (но с точностью до миллисекунды), --затраченное внутри .NET Framework объекты среды CLR во время последнего выполнения плана. --Объекты среды CLR могут быть хранимыми процедурами, функциями, триггерами, типами и статистическими выражениями ,qs.[max_last_clr_time] --Максимальное время, в микросекундах (но с точностью до миллисекунды), --затраченное внутри .NET Framework объекты среды CLR во время последнего выполнения плана. --Объекты среды CLR могут быть хранимыми процедурами, функциями, триггерами, типами и статистическими выражениями ,qs.[min_clr_time] --Минимальное время, когда-либо затраченное на выполнение плана внутри объектов .NET Framework среды CLR, --в микросекундах (но с точностью до миллисекунды). --Объекты среды CLR могут быть хранимыми процедурами, функциями, триггерами, типами и статистическими выражениями ,qs.[max_clr_time] --Максимальное время, когда-либо затраченное на выполнение плана внутри среды CLR .NET Framework, --в микросекундах (но с точностью до миллисекунды). --Объекты среды CLR могут быть хранимыми процедурами, функциями, триггерами, типами и статистическими выражениями --,qs.[total_elapsed_time] --Общее время, затраченное на выполнение плана, в микросекундах (но с точностью до миллисекунды) ,qs.[min_last_elapsed_time] --Минимальное время, затраченное на последнее выполнение плана, в микросекундах (но с точностью до миллисекунды) ,qs.[max_last_elapsed_time] --Максимальное время, затраченное на последнее выполнение плана, в микросекундах (но с точностью до миллисекунды) ,qs.[min_elapsed_time] --Минимальное время, когда-либо затраченное на выполнение плана, в микросекундах (но с точностью до миллисекунды) ,qs.[max_elapsed_time] --Максимальное время, когда-либо затраченное на выполнение плана, в микросекундах (но с точностью до миллисекунды) ,qs.[total_rows] --Общее число строк, возвращаемых запросом. Не может иметь значение null. --Значение всегда равно 0, если скомпилированная в собственном коде хранимая процедура запрашивает оптимизированную для памяти таблицу ,qs.[min_last_rows] --Минимальное число строк, возвращенных последним выполнением запроса. Не может иметь значение null. --Значение всегда равно 0, если скомпилированная в собственном коде хранимая процедура запрашивает оптимизированную для памяти таблицу ,qs.[max_last_rows] --Максимальное число строк, возвращенных последним выполнением запроса. Не может иметь значение null. --Значение всегда равно 0, если скомпилированная в собственном коде хранимая процедура запрашивает оптимизированную для памяти таблицу ,qs.[min_rows] --Минимальное количество строк, когда-либо возвращенных по запросу во время выполнения один --Значение всегда равно 0, если скомпилированная в собственном коде хранимая процедура запрашивает оптимизированную для памяти таблицу ,qs.[max_rows] --Максимальное число строк, когда-либо возвращенных по запросу во время выполнения один --Значение всегда равно 0, если скомпилированная в собственном коде хранимая процедура запрашивает оптимизированную для памяти таблицу ,qs.[total_dop] --Общую сумму по степени параллелизма плана используется с момента его компиляции. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[min_last_dop] --Минимальная степень параллелизма, если время последнего выполнения плана. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[max_last_dop] --Максимальная степень параллелизма, если время последнего выполнения плана. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[min_dop] --Минимальная степень параллелизма этот план когда-либо используется во время одного выполнения. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[max_dop] --Максимальная степень параллелизма этот план когда-либо используется во время одного выполнения. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[total_grant_kb] --Общий объем зарезервированной памяти в КБ предоставить этот план, полученных с момента его компиляции. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[min_last_grant_kb] --Минимальный объем зарезервированной памяти предоставляет в КБ, когда время последнего выполнения плана. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[max_last_grant_kb] --Максимальный объем зарезервированной памяти предоставляет в КБ, когда время последнего выполнения плана. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[min_grant_kb] --Минимальный объем зарезервированной памяти в КБ предоставить никогда не получено в ходе одного выполнения плана. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[max_grant_kb] --Максимальный объем зарезервированной памяти в КБ предоставить никогда не получено в ходе одного выполнения плана. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[total_used_grant_kb] --Общий объем зарезервированной памяти в КБ предоставить этот план, используемый с момента его компиляции. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[min_last_used_grant_kb] --Минимальная сумма предоставления используемой памяти в КБ, если время последнего выполнения плана. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[max_last_used_grant_kb] --Максимальная сумма предоставления используемой памяти в КБ, если время последнего выполнения плана. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[min_used_grant_kb] --Минимальный объем используемой памяти в КБ предоставить никогда не используется при выполнении одного плана. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[max_used_grant_kb] --Максимальный объем используемой памяти в КБ предоставить никогда не используется при выполнении одного плана. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[total_ideal_grant_kb] --Общий объем идеальный память в КБ, оценка плана с момента его компиляции. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[min_last_ideal_grant_kb] --Минимальный объем памяти, идеальным предоставляет в КБ, когда время последнего выполнения плана. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[max_last_ideal_grant_kb] --Максимальный объем памяти, идеальным предоставляет в КБ, когда время последнего выполнения плана. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[min_ideal_grant_kb] --Минимальный объем памяти идеальный предоставления в этот план когда-либо оценка во время выполнения один КБ. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[max_ideal_grant_kb] --Максимальный объем памяти идеальный предоставления в этот план когда-либо оценка во время выполнения один КБ. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[total_reserved_threads] --Общая сумма по зарезервированным параллельного потоков этот план когда-либо использовавшегося с момента его компиляции. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[min_last_reserved_threads] --Минимальное число зарезервированных параллельных потоков, когда время последнего выполнения плана. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[max_last_reserved_threads] --Максимальное число зарезервированных параллельных потоков, когда время последнего выполнения плана. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[min_reserved_threads] --Минимальное число зарезервированных параллельного потоков, когда-либо использовать при выполнении одного плана. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[max_reserved_threads] --Максимальное число зарезервированных параллельного потоков никогда не используется при выполнении одного плана. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[total_used_threads] --Общая сумма используется параллельных потоков этот план когда-либо использовавшегося с момента его компиляции. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[min_last_used_threads] --Минимальное число используемых параллельных потоков, когда время последнего выполнения плана. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[max_last_used_threads] --Максимальное число используемых параллельных потоков, когда время последнего выполнения плана. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[min_used_threads] --Минимальное число используемых параллельных потоков, при выполнении одного плана использовали. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти ,qs.[max_used_threads] --Максимальное число используемых параллельных потоков, при выполнении одного плана использовали. --Он всегда будет равно 0 для запроса к таблице, оптимизированной для памяти from tbl_res_rec as t left outer join sys.dm_exec_query_memory_grants as mg on t.[plan_handle]=mg.[plan_handle] and t.[sql_handle]=mg.[sql_handle] left outer join sys.dm_exec_cached_plans as pl on t.[plan_handle]=pl.[plan_handle] left outer join tbl_rec_stat_g as qs on t.[plan_handle]=qs.[plan_handle] and t.[sql_handle]=qs.[sql_handle] --and qs.[last_execution_time]=cast(t.[start_time] as date); 

    Также напомню, что по собранным статистикам можно получить самые тяжелые запросы:

    /* creation_time - Время, когда запрос был скомпилирован. Поскольку при старте сервера кэш пустой, данное время всегда больше либо равно моменту запуска сервиса. Если время, указанное в этом столбце позже, чем предполагаемое (первое использование процедуры), это говорит о том, что запрос по тем или иным причинам был рекомпилирован. last_execution_time - Момент фактического последнего выполнения запроса. execution_count - Сколько раз запрос был выполнен с момента компиляции Количество выполнений позволяет найти ошибки в алгоритмах - часто в наиболее выполняемых запросах оказываются те, которые находятся внутри каких-либо циклов однако могут быть выполнены перед самим циклом один раз. Например, получение каких-либо параметров из базы данных, не меняющихся внутри цикла. CPU - Суммарное время использования процессора в миллисекундах. Если запрос обрабатывается параллельно, то это время может превысить общее время выполнения запроса, поскольку суммируется время использования запроса каждым ядром. Во время использования процессора включается только фактическая нагрузка на ядра, в нее не входят ожидания каких-либо ресурсов. Очевидно, что данный показатель позволяет выявлять запросы, наиболее сильно загружающие процессор. AvgCPUTime - Средняя загрузка процессора на один запрос. TotDuration - Общее время выполнения запроса, в миллисекундах. Данный параметр может быть использован для поиска тех запросов, которые, независимо от причины выполняются "наиболее долго". Если общее время выполнения запроса существенно ниже времени CPU (с поправкой на параллелизм) - это говорит о том, что при выполнения запроса были ожидания каких-либо ресурсов. В большинстве случаев это связано с дисковой активностью или блокировками, но также это может быть сетевой интерфейс или другой ресурс. Полный список типов ожиданий можно посмотреть в описании представления sys.dm_os_wait_stats. AvgDur - Среднее время выполнения запроса в миллисекундах. Reads - Общее количество чтений. Это пожалуй лучший агрегатный показатель, позволяющий выявить наиболее нагружающие сервер запросы. Логическое чтение - это разовое обращение к странице данных, физические чтения не учитываются. В рамках выполнения одного запроса, могут происходить неоднократные обращения к одной и той же странице. Чем больше обращений к страницам, тем больше требуется дисковых чтений, памяти и, если речь идет о повторных обращениях, большее время требуется удерживать страницы в памяти. Writes - Общее количество изменений страниц данных. Характеризует то, как запрос "нагружает" дисковую систему операциями записи. Следует помнить, что этот показатель может быть больше 0 не только у тех запросов, которые явно меняют данные, но также и у тех, которые сохраняют промежуточные данные в tempdb. AggIO - Общее количество логических операций ввода-вывода (суммарно) Как правило, количество логических чтений на порядки превышает количество операций записи, поэтому этот показатель сам по себе для анализа применим в редких случаях. AvgIO - Среднее количество логических дисковых операций на одно выполнение запроса. Значение данного показателя можно анализировать из следующих соображений: Одна страница данных - это 8192 байта. Можно получить среднее количество байт данных, "обрабатываемых" данным запросом. Если этот объем превышает реальное количество данных, которые обрабатывает запрос (суммарный объем данных в используемых в запросе таблицах), это говорит о том, что был выбран заведомо плохой план выполнения и требуется заняться оптимизацией данного запроса. Я встречал случай, когда один запрос делал количество обращений, эквивалентных объему в 5Тб, при этом общий объем данных в это БД был 300Гб, а объем данных в таблицах, задействованных в запросе не превышал 10Гб. В общем можно описать одну причину такого поведения сервера - вместо использования индекса сервер предпочитает сканировать таблицу или наоборот. Если объем логических чтений в разы превосходит общие объем данных, то это вызвано повторным обращениям к одним и тем же страницам данных. Помимо того, что в одном запросе таблица может быть использована несколько раз, к одним и тем же страницам сервер обращается например в случаях, когда используется индекс и по результатам поиска по нему, найденные некоторые строки данных лежат на одной и той же странице. Конечно, в таком случае предпочтительным могло бы быть сканирование таблицы - в этом случае сервер обращался бы к каждой странице данных только один раз. Однако этому часто мешают. попытки оптимизации запросов, когда разработчик явно указывает, какой индекс или тип соединения должен быть использован. Обратный случай - вместо использования индекса было выбрано сканирование таблицы. Как правило, это связано с тем, что статистика устарела и требуется её обновление. Однако и в этом случае причиной неудачно выбранного плана вполне могут оказаться подсказки оптимизатору запросов. query_text - Текст самого запроса database_name - Имя базы данных, в находится объект, содержащий запрос. NULL для системных процедур object_name - Имя объекта (процедуры или функции), содержащего запрос. */ with s as ( select creation_time, last_execution_time, execution_count, total_worker_time/1000 as CPU, convert(money, (total_worker_time))/(execution_count*1000)as [AvgCPUTime], qs.total_elapsed_time/1000 as TotDuration, convert(money, (qs.total_elapsed_time))/(execution_count*1000)as [AvgDur], total_logical_reads as [Reads], total_logical_writes as [Writes], total_logical_reads+total_logical_writes as [AggIO], convert(money, (total_logical_reads+total_logical_writes)/(execution_count + 0.0))as [AvgIO], [sql_handle], plan_handle, statement_start_offset, statement_end_offset from sys.dm_exec_query_stats as qs with(readuncommitted) where convert(money, (qs.total_elapsed_time))/(execution_count*1000)>=100 --выполнялся запрос не менее 100 мс ) select s.creation_time, s.last_execution_time, s.execution_count, s.CPU, s.[AvgCPUTime], s.TotDuration, s.[AvgDur], s.[Reads], s.[Writes], s.[AggIO], s.[AvgIO], --st.text as query_text, case when sql_handle IS NULL then ' ' else(substring(st.text,(s.statement_start_offset+2)/2,( case when s.statement_end_offset =-1 then len(convert(nvarchar(MAX),st.text))*2 else s.statement_end_offset end - s.statement_start_offset)/2 )) end as query_text, db_name(st.dbid) as database_name, object_schema_name(st.objectid, st.dbid)+'.'+object_name(st.objectid, st.dbid) as [object_name], sp.[query_plan], s.[sql_handle], s.plan_handle from s cross apply sys.dm_exec_sql_text(s.[sql_handle]) as st cross apply sys.dm_exec_query_plan(s.[plan_handle]) as sp 

    Также можно и для MySQL написать. Для этого нужно установить mysql-connector-net и затем написать примерно такой код:

    Код для ожидающих запросов

    #Задаем переменные для подключение к MySQL и само подключение [string]$sMySQLUserName = 'UserName' [string]$sMySQLPW = 'UserPassword' [string]$sMySQLDB = 'db' [string]$sMySQLHost = 'IP-address' [void][System.Reflection.Assembly]::LoadWithPartialName("MySql.Data"); [string]$sConnectionString = "server="+$sMySQLHost+";port=3306;uid=" + $sMySQLUserName + ";pwd="+"'" + $sMySQLPW +"'"+ ";database="+$sMySQLDB; #Open a Database connection $oConnection = New-Object MySql.Data.MySqlClient.MySqlConnection($sConnectionString) $Error.Clear() try < $oConnection.Open() >catch < write-warning ("Could not open a connection to Database $sMySQLDB on Host $sMySQLHost. Error: "+$Error[0].ToString()) >#The first query # Get an instance of all objects need for a SELECT query. The Command object $oMYSQLCommand = New-Object MySql.Data.MySqlClient.MySqlCommand; # DataAdapter Object $oMYSQLDataAdapter = New-Object MySql.Data.MySqlClient.MySqlDataAdapter; # And the DataSet Object $oMYSQLDataSet = New-Object System.Data.DataSet; # Assign the established MySQL connection $oMYSQLCommand.Connection=$oConnection; # Define a SELECT query $oMYSQLCommand.CommandText='query'; $oMYSQLDataAdapter.SelectCommand=$oMYSQLCommand; # Execute the query $count=$oMYSQLDataAdapter.Fill($oMYSQLDataSet, "data"); $result = $oMYSQLDataSet.Tables[0].Rows[0]["Count"]; write-host $result; 

    Результат

    В данной статье был рассмотрен пример счетчиков производительности (элементы данных) в Zabbix. Данный подход позволяет уведомлять администраторов о разных проблемах в реальном времени или через какое-то определенное время. Таким образом, данный подход позволяет минимизировать в будущем наступления критической проблемы и остановки работы СУБД и сервера, что в свою очередь защищает производство от остановки рабочих процессов.
    Предыдущая статья: Регламентные работы с базой данных информационной системы 24x7 в MS SQL Server

    2 Выражение триггера

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

    Простое полезное выражение может выглядеть примерно так:

     :.()>оператор>константа>
    Функции

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

    Параметры функций

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

    Вы можете использовать префикс #, чтобы указать что этот параметр должен иметь другой смысл:

    ВЫЗОВ ФУНКЦИИ СМЫСЛ
    sum(600) Сумма всех значений за 600 секунд
    sum(#5) Сумма последних 5 значений

    Функция last использует другой смысл для значений, когда начинается с решетки - она дает выбрать n-ое предыдущее значение, так что с учетом значений 3, 7, 2, 6, 5 (от наиболее нового до наиболее старого), при last(#2) вернется 7 и при last(#5) вернется 5.

    Несколько функций поддерживают дополнительный, второй параметр сдвиг_времени . Этот параметр позволят ссылаться на данные из периода времени в прошлом. Например, для avg(1h,1d) будет возвращено среднее значение за час днем ранее.

    Вы можете использовать поддерживаемые суффиксы преобразований в выражениях триггеров, например, '5m' (минут) вместо '300' секунд или '1d' (день) вместо '86400' секунд. '1K' будет состоять из '1024' байт.

    Операторы

    Следующие операторы поддерживаются для триггеров (представлены по убыванию приоритета выполнения):

    ПРИОРИТЕТ ОПЕРАТОР ОПРЕДЕЛЕНИЕ Заметки по неизвестным значениям
    1 - Унарный минус -Неизвестно → Неизвестно
    2 not Логическое НЕ not Неизвестно → Неизвестно
    3 * Умножение 0 * Неизвестно → Неизвестно
    (да, Неизвестно, не 0 - чтобы не потерять
    Неизвестно в арифметических операциях)
    1.2 * Неизвестно → Неизвестно
    / Деление Неизвестно / 0 → ошибка
    Неизвестно / 1.2 → Неизвестно
    0.0 / Неизвестно → Неизвестно
    4 + Арифметический плюс 1.2 + Неизвестно → Неизвестно
    - Арифметический минус 1.2 - Неизвестно → Неизвестно
    5 Менее чем. Этот оператор может быть представлен в виде:

    Операторы not, and and or регистрозависимы и должны быть в нижнем регистре. Они также должны быть окружены символами пробелов или круглыми скобками.

    Все операторы, кроме унарных - и not, имеют ассоциативность слева на право. Унарные - и not не ассоциативны (имеется в виду необходимо использовать -(-1) и not (not 1) вместо --1 и not not 1).

    • Операторы , , >, >=, =, <> должны давать '1' в выражении триггера, если указанное соотношение правдиво и '0', если оно ложно. Если по крайней мере один операнд Неизвестен, то и результат будет Неизвестно;
    • and по известным операндам должно давать '1', если оба из этих операндов сравнения не равны '0'; в противном случае, будет давать '0'; для неизвестных операндов and даст '0' только, если один из операндов сравнения равен '0'; в противном случае, он даст 'Неизвестно';
    • or по известным операндам должно давать '1', если какой-либо из этих операндов сравнения не равен '0'; в противном случае, будет давать '0'; для неизвестных операндов or даст '1' только, если один из операндов сравнения не равен '0'; в противном случае, он даст 'Неизвестно';
    • Результат логического операнда отрицания not для известного операнда равен '0', если значение этого операнда сравнения не равно '0'; '1', если значение его операнда сравнения равно '0'. Для неизвестных операндов not даст 'Неизвестно'.
    Кэширование значений

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

    Примеры триггеров
    Пример 1

    Высокая загрузка процессора на www.zabbix.com.

    'www.zabbix.com:system.cpu.load[all,avg1]' представляет короткое имя наблюдаемого параметра. Эта строка указывает, что сервер - 'www.zabbix.com' и наблюдаемый ключ - 'system.cpu.load[all,avg1]'. Используя функцию 'last()', мы ссылаемся на самое последнее значение. И наконец '>5' означает, что триггер перейдет в состояние ПРОБЛЕМА всякий раз, когда самое новое измерение загрузки процессора на сервере www.zabbix.com будет превышать 5.

    Пример 2
      >5 or >2 

    Это выражение будет истинным, когда либо текущая загрузка процессора станет более 5, либо загрузка процессора больше значения 2 за последние 10 минут.

    Пример 3

    /etc/passwd был изменен

    Используется функция diff:

    Это выражение будет истинным, когда предыдущее значение контрольной суммы файла /etc/passwd отличается от самого нового значения.

    Аналогичные выражения могут быть полезны для мониторинга изменений в важных файлах, таких как /etc/passwd, /etc/inetd.conf, /kernel и других.

    Пример 4

    Кто-то скачивает большой файл из Интернет

    Используется функция min:

      >100K

    Это выражение будет истинным, когда количество полученных байт на eth0 превышает 100 КБ за последних 5 минут.

    Пример 5

    Оба узла кластера SMTP серверов недоступны

    Примечание, в выражении используются два разных узла сети:

      =0 and =0

    Это выражение будет истинным, когда оба SMTP сервера недоступны на обоих smtp1.zabbix.com и smtp2.zabbix.com.

    Пример 6

    Zabbix агент нуждается в обновлении

    Используется функция str():

    Это выражение будет истинным, когда версия Zabbix агента содержит в себе 'beta8' (возможно 1.0beta8).

    Пример 7

    Это выражение будет истинным, если узел сети “zabbix.zabbix.com" недоступен более 5 раз за последние 30 минут.

    Пример 8

    Нет данных за последние 3 минуты

    Используется функцию nodata():

    Для того, чтобы этот триггер заработал, элемент данных ‘tick’ должен быть задан как элемент данных типа Zabbix траппер. Узел сети должен периодически отправлять данные этому элементу данных, используя zabbix_sender. Если не было получено данных за последние 180 секунд, значением триггера станет ПРОБЛЕМА.

    Обратие внимание, что 'nodata' можно использовать с любым типом элементов данных.

    Пример 9

    Активность CPU в ночное время

    Используется функция time():

      >2 and >000000 and 060000

    Триггер может изменить свое состояние в истинное только в ночное время (00:00-06:00).

    Пример 10

    Проверка синхронизации времени на клиенте со временем на Zabbix сервере

    Используется функция fuzzytime():

    Триггер изменит состояние на проблему тогда, когда локальное время на сервере MySQL_DB и Zabbix сервере различаются более чем на 10 секунд.

    Пример 11

    Сравнение средней загрузки сегодня со средним значением загрузки за это же время вчера (использование второго параметра сдвиг_времени ).

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

    Пример 12

    Использование значение другого элемента данных в качестве порогового значения триггера:

     Template PfSense:hrStorageFree[ ].last()>Template PfSense:hrStorageSize[ ].last()>*0.1

    Триггер изменит свое состояние на проблему, если свободное пространство на диски упадет ниже 10 процентов.

    Пример 13

    Использование результата вычисления для получения количества триггеров больше порога:

     ( >5) + ( >5) + ( >5)>=2

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

    Гистерезис

    Порой нам необходим интервал между состояниями ОК и Проблема, а не просто порог. Например, мы бы хотели задать триггер, который переходит в состояние Проблема, когда температура в серверной комнате становится больше 20C и мы бы хотели чтобы он оставался в этом состоянии пока температура не опустится ниже 15C.

    Чтобы это сделать, сначала мы зададим выражение триггера для события о проблеме. Затем выберем 'Выражение восстановления' в Формирование ОК события и укажем выражение восстановления для ОК события.

    Обратите внимание, что выражение восстановления будет вычислено только при первом решении события о проблеме. Невозможно решить проблему при помощи выражения восстановления, если условие проблемы всё еще присутствует.

    Пример 1

    Температура в серверной комнате слишком высокая.

    Пример 2

    Очень мало свободного места на диске

    Выражение проблемы: если меньше 10ГБ за последние 5 минут

    Выражение восстановления: если больше 40ГБ за последние 10 минут

    Выражения с неподдерживаемыми элементами данных и неизвестными значениями

    Версии до Zabbix 3.2 очень строго относились к неподдерживаемым элементам данных в выражениях триггеров. Любой неподдерживаемый элемент данных в выражении незамедлительно менял значение триггера на Неизвестно .

    Начиная с Zabbix 3.2 существует более гибкий подход к неподдерживаемым элементам данных, допуская неизвестные значения при вычислении выражений:

    • У некоторых функций их значения не зависят от того поддерживается ли элемент данных или нет. Такие функции теперь вычисляются даже, если ссылаются на неподдерживаемые элементы данных. Смотрите список в разделе функции и неподдерживаемые элементы данных.
    • Логические выражения с ИЛИ и И могут быть вычислены для известных значений в двух случаях независимо от неизвестных операндов:
      • "1 or Неподдерживаемый_элемент_данных1.некая_функция() or Неподдерживаемый_элемент_данных2. некая_функция() or . " может быть вычислена как '1' (Правда),
      • "0 and Неподдерживаемый_элемент_данных1. некая_функция() and Неподдерживаемый_элемент_данных2. некая_функция() and . " может быть вычислена как '0' (Ложь).
        Zabbix пытается вычислить логические выражения принимая неподдерживаемые элементы данных как Неизвестные значения. В двух случаях, упомянутых выше, будет приниматься известное значение; в остальных случаях значением триггера будет Неизвестно .

      Обратите внимение на то, что неизвестные значения могут "исчезать" только в логических выражениях описанных выше. В арифметических выражениях неизвестные Неизвестному результату (за исключением деления на 0).

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *