О теме доклада
Наверное, каждый сталкивался с фразой: «У нас все висит, тормозит, ничего не работает – помогите!»
Что, как правило, делает 1С-ник? Открывает диспетчер задач, в лучшем случае видит загрузку памяти и начинает ее чистить, в худшем – видит картину, когда все вроде бы хорошо, но все тормозит. Тогда начинаются рестарты всего, что можно рестартовать.
В какой-то момент мне надоели рестарты и чистки кэша, я начал разбираться с вопросами производительности и попутно получил сертификат эксперта по технологическим вопросам.
По своему опыту и опыту коллег скажу, что все тормоза, как правило, возникают из-за неоптимального кода 1С, написанного программистами. Реже – из-за настройки серверов, СУБД и т.д. В любом случае, нет волшебной «галочки», которую можно поставить – и все летает.
В докладе:
-
разберем тормозящие запросы и что с ними делать;
-
научимся убирать ожидания на СУБД MS SQL Server;
-
узнаем, как чинить падающие рабочие процессы сервера 1С.
Первая проблема
Это был старт проекта на ERP:
-
Из типовой ERP использовалось очень мало, буквально пара подсистем. При этом был очень большой самописный модуль.
-
Серверы 1С и СУБД совмещены.
-
Оборудование не загружено.
-
RLS нет.
-
Но при этом все тормозит.
Начали разбираться. Взяли для примера одну типовую операцию – открытие формы документа. Причем, это был простой самописный документ без сложных наворотов.
Обычный замер производительности из конфигуратора показал, что под полными правами все работает и открывается быстро, а под неполными открывается 11 секунд.
Сразу же видно разницу в запросах. На первом месте у меня запрос, который выполняется больше трех секунд под неполными правами, а подо мной выполняется за сотые доли секунды.
Наверное, все подумали о том, что проблема во все-таки включенном RLS, потому все и тормозит. Я тоже так решил и пошел его проверять. Оказалось, что он отключен.
Я собрал технологический журнал конкретно по проблемному запросу, выполнил его под собой и под пользователем с неполными правами.
Оказалось, что тексты запросов, которые передавались на SQL, были абсолютно одинаковые. И, что более важно, абсолютно одинаковым было и время выполнения.
На слайдах отмечено время в микросекундах – оба запроса выполняются почти мгновенно.
Откуда тогда могло взяться 3 секунды?
Давайте погрузимся в теорию. На слайде – типовая картинка с ИТС, показывающая клиент-серверную архитектуру. У нас все было примерно так же. Не было никаких веб-серверов, отладки по HTTP и т.д. – только тонкие клиенты.
Какие компоненты могут тормозить?
-
Первое – СУБД, но она у нас не тормозит. Техжурнал показал, что запрос выполняется быстро.
-
Второе – сеть между 1С и СУБД. Но она тоже не может тормозить, потому что ее попросту нет – у нас для сервера СУБД и сервера 1С используется одна машина. Плюс включен протокол Shared memory – используется общая оперативная память. Сети вообще нет, грубо говоря.
-
Клиенты и сеть между клиентами сервера тормозить вообще не могли, потому что у нас проблема в запросе. Клиентов мы сразу отметаем, все запросы выполняются на сервере.
-
Остается одно звено – сервер 1С, с ним что-то было не так.
А что было не так?
Смотрим дальше.
-
Посмотрел, сколько ролей у проблемных пользователей. Оказалось – 1261 роль.
-
Напоминаю, что у нас ERP с подсистемами, которые не использовались. И однажды был создан профиль, который назывался «Для всех». Туда были добавлены вообще все типовые роли ERP без разбора – получилось столько ролей.
-
Также я сохранил конфигурацию в файлы, когда каждый объект метаданных сохраняется в отдельный файлик.
-
Посмотрел размер файлов ролей, и получилось так, что когда мы добавляем самописную роль, мы ставим в нее только пару галочек, поэтому она весит буквально несколько килобайт. А типовые роли за счет ограничений доступа, написанных для RLS, достаточно тяжелые. Они весят мегабайты, максимально – 25 мегабайт.
-
Убрали лишние роли, оставили порядка 150 штук, и все заработало быстро.
Точно не могу сказать, что повлияло: количество или вес ролей. Такого эксперимента мы не проводили, но суть в том, что убрали лишнее – заработало.
Выводы.
-
Не давать пользователю все роли без разбора, 1261 роль – это достаточно много.
-
Если порассуждать по поводу запроса, на котором были тормоза, то это был очень простой запрос с выборкой из основной таблицы одного регистра сведений. Без соединений, но с одним нюансом – там выбиралось порядка сотни полей.
-
Такое ощущение, что три секунды уходило на то, чтобы сервер 1С сформировал из текста запроса на языке 1С текст запроса на языке SQL. Возможно, он пытался для каждого поля поискать ограничения в выбранных для пользователя ролях. Но, так как он их не находил, то отправлял запрос точно такой же.
На слайде стоят знаки вопросов. Возможно, кто-то меня поддержит, а кто-то опровергнет мои догадки и кинет в меня ссылкой, потому что официального подтверждения своим догадкам я так и не нашел. Такой повод для дискуссий.
Вторая проблема
Перейдем к следующей проблеме:
-
Нагрузочный тест на 600 пользователей.
-
Использовалась также ERP, но практически типовая.
-
Серверы 1С и СУБД разнесены.
-
При начале итерации теста CPU на сервере СУБД возрастало до 100% и не отпускало несколько минут.
Предприняли самые простые действия.
Собрали трассировку запросов на SQL, сгруппировали, отсортировали по CPU.
На первом месте с большим отрывом – занимал в десять раз больше CPU, чем второе место – оказалось заполнение панельки «Текущие дела». По мере наполнения базы у нас этот запрос выполнялся порядка 15-20 минут. Оно крутится в фоне, никто этого не замечает, но оно нагружает базу.
Удалили эту панельку, стало легче.
Но раз уж я занимался СУБД, решил заглянуть в механизм ожиданий на SQL. Тут тоже будет немного теории.
Наверное, многие знают, что в SQL есть механизм системных динамических административных представлений – DMV. С помощью него можно посмотреть всевозможные данные о работе сервера: размер баз, таблиц, состояние индексов, когда делаются бэкапы, все, что угодно.
-
Одно из таких представлений – sys.dm_os_wait_stats. Оно накапливает статистику с момента старта сервера – на чем ожидают запросы: когда запрос хочет, но не может выполниться из-за того, что чего-то ждет. Самый простой пример – блокировки.
-
DMV sys.dm_exec_requests – запросы, которые выполняются прямо сейчас, в эту секунду. Можно посмотреть, сколько они будут выполняться, и ждут ли они чего-то. А если ждут – чего им не хватает.
Есть несколько основных типов ожидания – они перечислены на слайде, подробно рассказывать не буду.
-
В целом, я ожидал увидеть первый тип, который называется SOS_SHEDULER_YIELD. Если вы его видите на SQL – это значит, что у вас просто малоядерное ЦПУ. Так как у нас была нагрузка, я ожидал увидеть его.
-
Также есть несколько типов, которые говорят о недостаточной производительности дисков – PAGEIOLATCH и WRITELOG
-
И еще один тип ASYNC_NETWORK_IO, который означает, что у вас либо проблема с сетью, либо сервер 1С перегружен настолько, что не может принять результат какого-то запроса.
-
Самое простое – LCK, блокировки.
По ссылке приведено описание всех типов ожиданий, но нужно понимать, что большинство из них не являются проблемой.
Итак, мы выполнили запрос к DMV sys.dm_os_wait_stats:
-
SOS_SHEDULER_YELD, который я ожидал увидеть, оказался на втором месте и занимал всего 6% от всех ожиданий;
-
а на первом месте был некий PAGELATCH_UP.
Еще скриншоты с таблицы sys.dm_exec_requests, где показан список запросов, которые выполняются прямо сейчас.
На этом слайде показано 15 запросов, и все они ждут.
Здесь – 12 запросов.
Здесь – 18.
В пике уходило до 100 запросов, и время ожидания доходило до полсекунды. Это очень долго и очень плохо.
Прочитал определение PAGELATCH_UP – это тип ожидания, который имеет место, когда задача ожидает кратковременной блокировки буфера, находящегося не в состоянии запроса ввода-вывода.
Прочел раза четыре, ничего не понял, и начал искать более понятное определение.
Выяснил, что Latches – внутренние блокировки SQL-сервера, которые должны быть очень легкими и короткими, незаметными. И они блокируют доступ не на диске, а в оперативной памяти.
Давайте посмотрим, откуда они могли у нас взяться.
Если посмотреть внимательно на скриншоты таблички sys.dm_exec_requests – с запросами, которые выполнялись прямо сейчас – видно, что:
-
мы всегда ждем один и тот же ресурс – это некая страница 2:1:2;
-
все операции – запросы к базе tempdb, операции с #tt.
-
мы видим здесь команды CREATE TABLE (создание таблицы) и TRUNCATE TABLE (очистка таблицы).
Здесь еще несколько скриншотов и везде – CREATE TABLE и TRUNCATE TABLE, только страницы другие – 2:3:2, 2:4:2, 2:5:2.
Чтобы понять, что это за страницы, еще раз обращусь к теории.
-
Многие знают, что в MS SQL Server данные хранятся в страницах. Каждая страница занимает 8 килобайт. И это не настраивается. В PostgreSQL, по-моему, настраивается, но тоже лучше не менять.
-
Страницы, в свою очередь, объединяются в экстенты, по 8 страниц в каждом.
-
В MS SQL Server есть два типа экстентов: однородные и смешанные.
-
однородные – когда в экстенте хранятся данные только по одной таблице;
-
а смешанные – когда можем положить в него 8 разных страниц с данными по разным таблицам и индексам.
-
На слайде приведено куча определений – их можно не читать, я постараюсь донести суть.
В каждой базе на MS SQL Server есть ряд служебных страниц, которые контролируют заполненность наших страниц и экстентов.
Когда мы пытаемся добавить, записать какие-то данные, MS SQL Server обращается к картам, смотрит, что у него тут экстент свободный, тут – половинка и там – половинка, и решает, куда класть данные. После этого делает отметку в карте, что экстент заполнен, туда больше ничего не положить.
При очистке – то же самое, только наоборот. MS SQL Server данные из страницы убирает и ставит отметку в карту, что там свободно, можно что-то класть.
В случае с обычной базой данных это не так критично, потому что мы в нее не так часто пишем и удаляем данные. Чтобы увидеть такие ожидания в запросах пользовательской базы данных, у этой базы должна быть очень крутая загрузка. Как минимум тысяча пользователей.
В случае с базой tempdb все как раз наоборот. 1С-ка с ней работает очень интенсивно – постоянно создает и очищает таблицы, на скриншотах это как раз и было видно – CREATE TABLE, TRUNCATE TABLE. Они на tempdb выполняются постоянно.
Как раз на этих картах у нас и было ожидание – страница 2:1:2 как раз отвечает за то, какие экстенты у нас заняты.
Решение здесь простое:
-
Разбить базу tempdb на несколько файлов. На сколько разбить? Рекомендации сайта ИТС говорят, что надо разбивать на 4 части.
Я нашел более универсальную формулу: если у вас количество ядер меньше 8, то количество файлов должно быть равно количеству ядер, а если больше или равно – то количество файлов = 8. В целом, думаю, можно бить просто на 8 файлов и не париться – хуже не будет. Мы так и сделали, ожидания ушли. -
Вторая рекомендация с сайта ИТС: флаг трассировки 1118. Этот флаг запрещает создание смешанных экстентов. Я этого не делал – мне хватило первой рекомендации. Но если у вас конкуренция за доступ к ресурсу 2:1:3, который отвечает как раз за смешанные экстенты – можно попробовать включить этот флаг. Но пользоваться этим нужно аккуратно, потому что если вы отключите смешанные экстенты, база будет расти.
Третья проблема
Еще одна ситуация:
-
Платформа 8.3.15.
-
Сервер 1С и сервер СУБД разнесены,
-
На сервере 1С – пять баз.
-
Оборудование не загружено, проблем с производительностью не было никаких, работало все достаточно быстро.
-
Но периодически вываливались непонятные ошибки.
Например, на слайде показана ошибка, с которой закрывалась 1С в разных базах, у разных пользователей. Это доставляло дискомфорт, с этим нужно было что-то сделать.
Для исследования настроили все возможные мониторинги.
-
Техжурнал с событиями, которые отвечают за работу сервера 1С: ATTN, PROC, CLSTR и тд.
-
Счетчики производительности Windows конкретно для процессов 1С: rphost, ragent, rmngr.
-
Изменили одну настройку: количество ИБ на процесс. У нас было 2, установили единицу.
Для чего это сделано? Когда количество ИБ=2, у вас один rphost хоть каждый день может обслуживать разные базы: в первый день у вас rphost обслуживает 1С:ERP и 1C:Документооборот, во второй день – 1С:Документооборот и БП, в третий – ЗУП и ERP и т. д. Когда возникает ошибка с падением – мы вылетаем из двух разных баз.
Чтобы понять: проблемы в какой-то из баз или платформа падает сама по себе – сделана вот такая настройка, что один rphost обслуживает одну базу.
Это дало результат – мы обнаружили, что падает только ERP. Мы хотя бы починили 4 базы из 5 – они падать перестали.
На слайде показан скриншот дампов, которые создавались из-за падений процессов. Здесь видно, что нет никакой закономерности, база падает каждый день по несколько раз. Из этого ничего было особо непонятно.
Это график потребления памяти одним из упавших rphost-ов. График получен с помощью стандартного мониторинга производительности Windows – Perfmon.
Мы видим график памяти:
-
перед падением нет никакого скачка, роста потребления;
-
нет и падения – не видно, что он пытается это отпустить, передать соединение на другой rphost;
-
он просто идет, живет своей жизнью и резко обрывается.
Снизу – запись rphost-а перед падением. В них нет описания ошибки, есть исключение операционной системы и больше никакой информации: «Я устал, я ухожу – вот тебе дамп, делай с ним, что хочешь».
Зачастую, когда падают rphost-ы, в логах rphost последней записью бывает прямо строчка кода, из-за чего он рухнул. И тогда сразу становится понятно, куда смотреть и что произошло. Но тут такого не было.
Дальше:
-
Попробовали открывать наши созданные дампы. Там были ссылки на библиотеку Windows, которая не могла быть источником проблемы.
-
Пособирали полный техжурнал, попытались найти закономерности – это нам тоже ничего не дало.
-
Тогда мы поставили экстремальную настройку, количество соединений на процесс = 1, из-за которой для каждого соединения создавался свой rphost. Нам повезло, что заказчик был достаточно лояльный и пошел нам навстречу с тяжелыми экспериментами. В результате rphost-ов было больше 100, все очень сильно тормозило, пользователи так поработали полдня. За эти полдня мы выловили несколько падений, надеялись увидеть какую-то закономерность: какой пользователь падает, выполняется ли перед этим какой-то запрос или форма. Нам это ничего не дало. Каждое падение было уникальным.
Идеи стали заканчиваться. Мы исследовали багборд 1С на предмет ошибок платформы и ERP, но ничего похожего по нашим симптомам не нашли. Google тоже ничего похожего не дал.
Решение нашлось случайно на партнерском форуме 1С. Там уже была создана тема с точно такими же симптомами, как у нас. Оказалось, что проблема была во внешней компоненте печати штрихкодов, которая лежит в общем макете в базе ERP.
Мы не нашли никаких ошибок, потому что эта компонента входит в состав библиотеки подключаемого оборудования. Когда мы искали ошибки на багборде, их нужно было искать не в платформе, не в системе, а в библиотеке.
Скачали новую библиотеку, обновили этот макет и падения ушли.
Вопросы
Создаваемые вами роли были отдельные (одна роль на один объект) или составные? И как вы догадались, что вес роли влияет на производительность? Это просто был перебор всех возможных комбинаций?
Роли мы создавали отдельные на каждый объект, составных ролей не было. А по поводу веса – не знаю, как догадался. То ли вычитал в интернете, то ли сам решил сделать это. Я до сих пор не уверен, что именно вес здесь вызвал проблему. Возможно, проблема была в количестве полей.
Поделитесь, какая версия MS SQL Server была, что вы словили проблему с tempbd с PAGELATCH_UP. Современный MS SQL Server по умолчанию ставит 8 файлов для tempdb.
У нас был MS SQL Server 2014. И там по умолчанию стоял один файл для tempdb.
*************
Данная статья написана по итогам доклада (видео), прочитанного на INFOSTART MEETUP Ekaterinburg.Online.