Мониторинг MS SQL Server для 1С: счётчики и Zabbix — АйТи Фреш
· 15 мин чтения

Мониторинг MS SQL Server для 1С и учётных систем: ключевые счётчики и готовый шаблон Zabbix

Мониторинг MS SQL Server для 1С и учётных систем: ключевые счётчики и готовый шаблон Zabbix

Клиент всегда формулирует одинаково: «1С тормозит, сделайте что-нибудь». В девяти случаях из десяти виноват не код и не конфигурация. Упёрся MS SQL Server — не хватает памяти под буферный пул, диск не успевает отдавать страницы, tempdb захлёбывается во временных таблицах. Ниже — какие счётчики и DMV мы смотрим первыми, какие пороги нас настораживают и как за один вечер всё это разворачивается в Zabbix, чтобы больше не бегать с DBCC вручную при каждой жалобе.

Почему разбор всегда начинается с SQL Server, а не с конфигурации 1С

На нашем сопровождении — десятки баз 1С:Предприятие 8.3 в клиент-серверном варианте. От «Бухгалтерии» на пять пользователей до УТ и ЗУП на 40–50 рабочих мест. Платформа почти везде 8.3.20–8.3.27, СУБД — MS SQL Server 2016, 2019 или 2022 (Standard Edition, реже Web Edition на совсем небольших конфигурациях). Когда прилетает жалоба «стало тормозить», первый вопрос — не «что поменяли в конфигурации», а куда упёрся сервер БД. В память? В диск? В конкурентный доступ? Вот с этого мы и начинаем.

Причина в архитектуре 1С: тонкий или толстый клиент формирует запрос, платформа превращает его в T-SQL, а дальше вся тяжесть — на СУБД. Если у SQL Server не хватает оперативной памяти под буферный пул, каждый повторный запрос читает данные заново с диска. Если диск под базой или под tempdb не тянет по IOPS и латентности, любая операция с временными таблицами (а 1С генерирует их массово — виртуальные таблицы регистров, временные таблицы СКД) начинает залипать на PAGEIOLATCH. Пользователь при этом видит только зависшую форму и жалуется на «1С», хотя конфигурация тут ни при чём.

Дальше по делу: конкретные счётчики, которые мы снимаем при диагностике, пороги, которые на нашей практике сигнализируют о проблеме (где это не рекомендация Microsoft, а наш опыт — отмечу отдельно), и готовый шаблон для Zabbix. Разворачиваем его клиенту сразу, чтобы в следующий раз не приезжать на диагностику руками.

Память и буферный пул: где на самом деле «тормозит 1С»

Первое, что проверяем, — не хватает ли SQL Server оперативной памяти. Смотрим счётчики объекта SQLServer:Memory Manager и SQLServer:Buffer Manager (доступны и через Perfmon, и через DMV sys.dm_os_performance_counters).

Отдельно проверяем настройку max server memory (MB) в свойствах сервера — на терминальных серверах, где на одной машине крутится ещё и сама 1С, RDS-сессии или файловый сервер, дефолтный «неограниченный» лимит SQL Server регулярно душит остальные службы по памяти. Мы всегда выставляем явный лимит, оставляя операционной системе и остальным сервисам не менее 20–25% RAM, а на серверах с NUMA — считаем отдельно на узел через SQL Server:Buffer Node.

Счётчик / источникЧто показываетПорог, на который ориентируемся
SQLServer:Buffer Manager \ Page life expectancyСреднее время жизни страницы в буферном пуле, сек.<300 сек — официальный порог MS; для серверов >16 ГБ используем формулу (ГБ/4)×300 (оценка по практике)
SQLServer:Memory Manager \ Total Server Memory (KB)Память, фактически занятая под буферный пулСтабильно ≈ Target Server Memory и ≈ max server memory — сигнал «упёрлись в потолок»
SQLServer:Buffer Manager \ Buffer cache hit ratioДоля чтений из кэша, а не с диска<95% на рабочей нагрузке — оценка по практике, повод разбираться
sys.dm_os_process_memory (physical_memory_in_use_kb)Реальное потребление процесса sqlservr.exeСверяем с max server memory и физической RAM хоста

Диск: латентность важнее, чем «сколько всего IOPS»

Второй блок — подсистема хранения. Здесь мы смотрим не абсолютные IOPS (они у всех разные — HDD RAID, SSD, NVMe, виртуальный диск на гипервизоре), а именно латентность отклика, потому что 1С крайне чувствительна к задержкам на операциях с журналом транзакций и с tempdb.

Как понять, что сервер ждёт именно диск? Смотрим агрегированную статистику ожиданий:

SELECT wait_type, wait_time_ms, waiting_tasks_count FROM sys.dm_os_wait_stats WHERE wait_type IN ('PAGEIOLATCH_SH','PAGEIOLATCH_EX','WRITELOG','ASYNC_IO_COMPLETION') ORDER BY wait_time_ms DESC;

По документации Microsoft, если средние ожидания PAGEIOLATCH стабильно выше 10 мс — подсистема ввода-вывода под давлением: либо не хватает IOPS, либо диск физически не тот класс, что нужен под нагрузку. Ожидание WRITELOG отдельно указывает на журнал транзакций — часто это RAID-контроллер без battery-backed write cache или журнал, лежащий на том же массиве, что и файлы данных. Один из типовых P0-фиксов у нас на выезде — просто развести .mdf и .ldf по разным физическим томам, и жалобы на «тормозит проведение документов» снимаются без единого изменения в 1С.

CPU и параллелизм: когда тормозит не диск, а сам план запроса

Третий сценарий, который мы встречаем регулярно: SQL Server упирается не в диск и не в память, а в CPU. Причина — неудачно распараллеленные запросы. 1С генерирует немало тяжёлых аналитических запросов: отчёты, СКД, закрытие месяца. На многоядерных серверах SQL Server порой «раздувает» план на десятки потоков там, где выгоднее было бы выполнить его последовательно — и вместо ускорения получаем деградацию.

Диагностируем текущую нагрузку по CPU без сторонних утилит через sys.dm_exec_requests и sys.dm_exec_sessions — в паре с sys.dm_exec_sql_text это даёт список самых тяжёлых сейчас запросов с указанием конкретной сессии 1С (по host_process_id и program_name обычно видно, чей это клиентский процесс).

Блокировки и конкурентный доступ: когда «зависла» одна операция, а не весь сервер

Отдельная история — жалобы типа «завис у одного, у остальных всё нормально». Это почти всегда блокировки на уровне строк или таблиц, а не общая просадка сервера. Смотрим:

tempdb: самое частое узкое место в базах 1С, которое не видно из интерфейса программы

tempdb в 1С работает на порядок интенсивнее, чем в среднем OLTP-приложении: временные таблицы для виртуальных таблиц регистров, промежуточные результаты СКД, версии строк при включённом RCSI (см. предыдущий раздел) — всё это уходит именно туда. Если tempdb сконфигурирован «по умолчанию, одним файлом», то на нагруженной базе это стабильно узкое место.

Что проверяем и приводим в порядок:

Короткий скрипт, которым проверяем текущее число файлов tempdb и их размер — делаем это ещё до выезда к клиенту:

SELECT name, physical_name, size/128 AS size_mb, growth FROM tempdb.sys.database_files;

Готовый шаблон в Zabbix: как мы это автоматизируем у клиента

Ручной прогон DMV — разовая история. Чтобы не приезжать каждый раз, когда «опять тормозит», мы разворачиваем клиенту постоянный мониторинг на Zabbix. У большинства он уже стоит для мониторинга инфраструктуры — добавить туда MS SQL Server вопрос одного вечера.

Официальный путь — плагин MSSQL для Zabbix agent 2 (входит в поставку начиная с Zabbix agent 2 версии 6.0) и типовой шаблон «Microsoft SQL Server by Zabbix agent 2» из официального репозитория. Плагин подключается к SQL Server напрямую по протоколу TDS (порт 1433 по умолчанию), поэтому дополнительный ODBC-драйвер на сервере агента не требуется — только сетевая доступность и учётная запись SQL с правами VIEW SERVER STATE.

Шаги внедрения, которые мы повторяем у каждого клиента:

  1. Заводим отдельного SQL-логина только для мониторинга (не sa!) и даём ему GRANT VIEW SERVER STATE TO [zbx_monitor] — этого достаточно для чтения всех нужных DMV, права на изменение данных не нужны;
  2. Ставим или обновляем Zabbix agent 2 прямо на сервере с СУБД — либо на соседнем хосте, если агент там, но сетевой доступ к порту 1433 есть.
  3. В конфиге агента прописываем сессию подключения к базе.
  4. Импортируем в Zabbix Server шаблон Microsoft SQL Server by Zabbix agent 2, привязываем к узлу сети, назначаем макрос с именем сессии;
  5. Дефолтные пороги шаблона заточены под абстрактный «типовой» сервер. Для терминалок с 1С это не работает. Поэтому мы всегда подгоняем триггеры под конкретного клиента — PLE, латентность диска, RESOURCE_SEMAPHORE — ориентируясь на значения из таблиц выше.

Фрагмент конфигурации агента (zabbix_agent2.conf или отдельный .d-файл плагина):

Plugins.MSSQL.Sessions.MAIN1C.Uri=sqlserver://SQLSRV01:1433 Plugins.MSSQL.Sessions.MAIN1C.User=zbx_monitor Plugins.MSSQL.Sessions.MAIN1C.Password=<пароль_из_секрет-хранилища>

Быстрая проверка, что плагин вообще видит сервер — не дожидаясь опроса по расписанию:

zabbix_get -s 127.0.0.1 -k mssql.ping[MAIN1C]

Группа items в шаблонеЧто мониторимНаш триггер (клиентский профиль 1С)
Instance discoveryАвтообнаружение баз данных и job-ов SQL Agent на инстансеИнформационно, база для остальных LLD-правил
Performance counters (Buffer Manager)Page life expectancy, buffer cache hit ratioPLE ниже расчётного порога 15+ минут подряд — Warning; ниже 300 сек — Average
Memory ManagerTotal/Target Server Memory, Memory Grants PendingMemory Grants Pending > 0 дольше 5 минут — Average
Database statusСостояние БД (ONLINE/RESTORING и т.д.), размер файла логаСтатус ≠ ONLINE — Disaster (немедленно)
Backup discoveryВремя последнего успешного backup по каждой базеПолный backup давностью > 26 часов — Average (у 1С обычно ночной full + журнальные)
Job discovery (SQL Agent)Статус последнего выполнения job-ов обслуживания (реиндексация, backup)Последний запуск job = Failed — High

Отдельно на уровне ОС держим классический шаблон Windows by Zabbix agent (или Linux-аналог для SQL Server на Linux) для диска и памяти хоста — латентность и очередь диска технически относятся к ОС, а не к плагину MSSQL, и без них шаблон MSSQL показывает только «внутреннюю» картину сервера БД, без физического диска под ней.

Как читать дашборд целиком, а не по одному счётчику

Главная ошибка при самостоятельной настройке мониторинга — реагировать на один сработавший триггер без контекста. PLE ниже порога сам по себе ещё не диагноз. Если это случилось сразу после ночной реиндексации или рестарта службы SQL Server — всё нормально, буферный пул просто прогревается заново. Мы сталкивались с этим не раз: инженер поднимал панику ночью, а наутро оказывалось, что поводов не было.

Наш порядок разбора инцидента в Zabbix — сверху вниз, по убыванию вероятной причины:

  1. Первым делом смотрим триггеры Database status и Backup. База не в статусе ONLINE? Backup не проходил давно? Это приоритет №1 — к производительности не относится, но само по себе критично.
  2. Дальше смотрим Memory Grants Pending и PLE в паре. Оба красные и держатся уже несколько часов? Значит, проблема в памяти — идём разбираться с буферным пулом.
  3. Параллельно поднимаем графики диска на уровне ОС за тот же период: латентность и очередь. Если они тоже выросли — первопричина именно в диске, а память тут ни при чём. SQL Server просто агрессивнее цепляется за страницы, когда подкачка с диска работает медленно.
  4. Память в норме, диск в норме, а жалобы не прекращаются? Смотрим CPU и метрики RESOURCE_SEMAPHORE, CXPACKET. На нашей практике это почти всегда один тяжёлый отчёт или неудачный план запроса — никакой системной деградации, просто конкретная проблема в конкретном месте.

Этот порядок разбора мы фиксируем прямо в поле Description триггеров в Zabbix. Дежурный инженер, увидевший алерт в два часа ночи, сразу понимает, куда копать — и не звонит нам по каждому чиху.

Что это даёт на практике: конкретный пример из нашего сопровождения

Один показательный случай из практики. Терминальный сервер плюс SQL Server 2019 Standard на одной машине, база УТ 11 на 30+ рабочих мест. Жалобы «зависает при закрытии месяца» шли из месяца в месяц — и каждый раз списывались на тяжёлую операцию: мол, надо просто подождать. После того как мы развернули описанный мониторинг, картина прояснилась уже за первую неделю. PLE регулярно проваливался в момент ночного бэкапа: полная резервная копия писалась на тот же физический том, где лежали файлы данных, и вытесняла буферный пул. Одновременно в это же окно кратно подскакивали ожидания WRITELOG — журнал транзакций находился на том же диске. Два часа работы, одна понятная картина, решение очевидно.

Решение оказалось не в «добавить памяти» и не в «оптимизировать 1С», а в разнесении файлов: .ldf перенесли на отдельный SSD-том, окно backup сдвинули на менее нагруженное время и добавили сжатие backup средствами SQL Server, чтобы сократить время самой операции записи. После этого жалобы на закрытие месяца прекратились полностью, а метрики PLE и WRITELOG в Zabbix стали ровной линией без ночных провалов — именно эти графики мы и показываем клиенту как подтверждение, что проблема закрыта, а не «вроде стало лучше на слух».

Частые вопросы

Обязательно ли ставить ODBC-драйвер SQL Server, чтобы мониторить его через Zabbix?
Нет, если используете официальный плагин MSSQL для Zabbix agent 2 — он общается с сервером напрямую по протоколу TDS (тот же порт 1433, что и клиентские подключения 1С), отдельный ODBC-драйвер не требуется. ODBC нужен только если вы собираете метрики альтернативным способом через odbc.get и самописные шаблоны.
Почему Page Life Expectancy иногда падает даже на здоровом сервере?
Кратковременное падение PLE — ожидаемое поведение сразу после рестарта службы SQL Server, после ночной реиндексации/обновления статистики или сразу после резервного копирования, которое вытесняет часть буферного пула. Тревожный сигнал — не разовое падение, а устойчиво низкое значение в течение рабочего дня под обычной нагрузкой.
Нужно ли клиенту с 1С в файловом варианте (без сервера СУБД) что-то из этого мониторинга?
Нет, всё описанное относится к клиент-серверному варианту 1С:Предприятие с MS SQL Server. Файловая база (.1CD) работает без отдельной СУБД, и там симптомы медленной работы почти всегда связаны с сетевым диском, антивирусом или самим файлом базы, а не со счётчиками SQL Server.
Сколько занимает внедрение такого мониторинга у клиента, если Zabbix Server уже стоит?
По нашей практике — один визит: заведение SQL-логина для мониторинга с правом VIEW SERVER STATE, установка/обновление Zabbix agent 2, настройка сессии подключения к MSSQL-плагину и импорт официального шаблона с донастройкой порогов под конкретный сервер укладываются в несколько часов работы.
Что делать, если RESOURCE_SEMAPHORE регулярно в топе ожиданий, а памяти на сервере вроде достаточно?
Это ожидание указывает не на нехватку памяти вообще, а на нехватку memory grant под конкретный тяжёлый запрос (обычно сортировки или хэш-соединения в отчётах). Сначала находим сам запрос через sys.dm_exec_requests и sys.dm_exec_query_stats, и часто решение — переписать отчёт или обновить статистику, а не увеличивать max server memory.
📄
Скачайте подробный разбор в PDF Кейсы, статистика, типовые ошибки и чек-лист самопроверки — 12 страниц
Скачать PDF

Подпишитесь на разборы ITfresh

Раз в неделю присылаем практичные материалы по ИТ для бизнеса — без спама, только то, что реально пригодится.