Все думали на блокировки: детектив о вечернем пике, в котором виноват оказался параллелизм

25.08.26

База данных - HighLoad оптимизация

Каждый вечер в час закрытия смен 200 касс розничной сети начинали «залипать», и у всех было готовое объяснение: блокировки. Аудит ожиданий в час пика показал: блокировок — ноль. Сессии ждали не друг друга, а свободных потоков: заводские cost threshold for parallelism = 5 и MAXDOP = 0 на 48-ядерном сервере отправляли даже лёгкие запросы разбегаться по всем ядрам, и две трети запросов стояли в очереди за потоками. Разбираем детектив: почему рефлекс «вечером тормозит — значит, блокировки» подменяет диагностику, как читается картина ожиданий, причём тут сосед по инстансу с отчётом на 24 потока и 4,3 часа — и как две динамические настройки без перезапуска сняли проблему в тот же вечер. С чек-листом «блокировки или параллелизм».

Каждый вечер, в час закрытия смен, кассы розничной сети начинали «залипать». Не падать - именно залипать: операции, которые днём летали, вечером шли рывками, кассиры нервничали, закрытие растягивалось. Сеть немаленькая - около 200 касс в трёх странах, - и у всех участников было готовое объяснение: «вечером все закрываются одновременно - это блокировки».

Объяснение красивое, логичное и подтверждаемое жизненным опытом каждого, кто работал с 1С под нагрузкой. У него был только один недостаток: оно оказалось неверным. Это статья-детектив о том, как мы искали вечернего душителя касс, почему главный подозреваемый оказался невиновен и при чём здесь настройки сервера СУБД, оставшиеся заводскими с эпохи четырёхъядерных процессоров.

 

Почему все всегда думают на блокировки

«Вечером тормозит - значит, блокировки» - это рефлекс, и рефлекс не беспочвенный. Закрытие смены - действительно конкурентная операция: одновременные записи в одни регистры, длинные транзакции, пересечения по товарам. Каждый администратор 1С видел в своей жизни настоящие вечерние блокировки, и опыт подсказывает: ищи, кто кого ждёт.

Опасность рефлекса в том, что он подменяет диагностику. Команда начинает «бороться с блокировками»: переписывать проведение, дробить транзакции, крутить управляемые блокировки - а вечер за вечером ничего не меняется, потому что лечат не ту болезнь.

 

Аудит: главный подозреваемый невиновен

Мы начали с того, с чего надо начинать любую охоту на вечерний пик: не с гипотез, а с замеров. Сняли картину ожиданий на сервере СУБД именно в часы пика - кто чего ждёт, сколько и почему.

Результат обескуражил заказчика: блокировок в пик - ноль. Не «мало», не «в пределах нормы» - ноль значимых ожиданий на блокировках. Сессии не ждали друг друга. Они ждали кое-чего другого: свободных потоков процессора.

Картина ожиданий показывала классические признаки перегретого параллелизма: доминирующие ожидания обмена между потоками параллельных планов и - главное - очередь запросов, которым не хватило рабочих потоков. Две трети запросов в пик просто стояли в очереди за ресурсом, которого формально было в избытке: на сервере 48 ядер.

 

Механика удушения: как 48 ядер становятся узким местом

Чтобы понять, как сервер с 48 ядрами может задыхаться от нехватки потоков, нужно посмотреть на две настройки, которые в этой системе никто никогда не менял:

  • cost threshold for parallelism = 5 - порог «стоимости» запроса, после которого оптимизатор строит параллельный план. Значение 5 - заводское, и оно откалибровано под железо конца девяностых. По современным меркам «стоимость 5» - это лёгкий запрос: типичный отчётик, средней руки выборка. С таким порогом параллельным становится почти всё.
  • MAXDOP = 0 - максимальная степень параллелизма «без ограничений»: каждый параллельный запрос вправе разбежаться по всем ядрам сервера. Все 48.

Теперь сложим. Вечером сотни касс одновременно порождают поток запросов. Почти каждый из них (порог-то - 5) получает параллельный план. Почти каждый параллельный план (MAXDOP = 0) претендует на десятки потоков. Пул рабочих потоков сервера - конечный. Итог: лёгкие запросы, которым хватило бы одного ядра на долю секунды, выстраиваются в очередь за десятками потоков, которые им не нужны.

Это и есть вечерний душитель: не конкуренция за данные, а конкуренция за потоки, устроенная самим сервером из лучших побуждений. Днём, при меньшей плотности запросов, система прощала эти настройки. Вечером - переставала.

 

Отдельная серия: сосед по инстансу

У детектива был и второй сезон. SQL-сервер в этой инфраструктуре - общий: на одном инстансе живут десятки баз разных систем. В разгар работ весь сервер начал задыхаться уже не по вечерам, а среди дня. Виновник нашёлся быстро: отчёт из соседней базы - 24 параллельных потока, 4 часа 18 минут исполнения. Один запрос удерживал половину процессорных ресурсов сервера четыре часа подряд - при заводских настройках параллелизма он имел на это полное право.

Мораль для всех, кто живёт на общем инстансе: настройки параллелизма - общесерверные. Их выбирают не под одну базу, а под общежитие целиком, и «сосед с тяжёлым отчётом» - это ваш сосед, даже если база не ваша.

 

Лечение: две настройки, ноль перезапусков

Терапия заняла меньше времени, чем диагностика:

  • cost threshold for parallelism: 5 → 50. Лёгкие и средние запросы перестали получать параллельные планы - им и не нужно: одно ядро справляется быстрее, чем церемония раздачи работы десяткам потоков. Параллелизм остался тяжёлым отчётам и регламентным операциям - тем, кому он действительно помогает.
  • MAXDOP: 0 → 8. Даже тяжёлый запрос теперь ограничен восемью потоками - достаточно для ускорения, безопасно для соседей.

Обе настройки применяются динамически, без перезапуска сервера и без остановки работы - с заранее согласованным планом отката (вернуть старые значения - те же секунды). Конкретные числа не догма: 50 и 8 - разумная отправная точка для нагруженной 1С на многоядерном сервере, но правильные значения подбираются по картине ожиданий вашей системы, а не копируются из статей. Включая эту.

 

Результат

Вечерние «залипания» касс прекратились в тот же вечер. Очередь за потоками рассосалась: лёгкие запросы исполняются на одном ядре и не толкаются, тяжёлые получают свои восемь потоков и не захватывают сервер. Жалобы кассиров - привычный вечерний фон проекта - закончились.

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

 

Чек-лист: блокировки или параллелизм?

Если у вас «вечером всё тормозит», прежде чем объявлять войну блокировкам:

  1. Начните с картины ожиданий в час пика - стандартными средствами мониторинга СУБД. Диагноз до лечения: смотрите, чего именно ждут сессии.
  2. Ждут блокировок? Тогда классика: искать долгие транзакции и горячие объекты. Это отдельная дисциплина - и отдельная статья.
  3. Ждут потоков и обмена между потоками? Проверьте cost threshold for parallelism и MAXDOP. Заводские 5 и 0 на многоядерном сервере - мина, которая маскируется под «вечерние блокировки» десятилетиями.
  4. Общий инстанс? Помните: параллелизм настраивается на весь сервер, и самый тяжёлый запрос соседа - тоже ваша проблема.
  5. Меняете настройки - фиксируйте базовую линию до и картину после. Изменения динамические и обратимые, но «стало лучше» должно быть измерением, а не ощущением.
  6. Не копируйте чужие значения вслепую - подбирайте по своей картине ожиданий. Отправная точка и метод важнее конкретных чисел.

 

А если доступа к SQL Server у вас нет

Совет "снимите картину ожиданий" упирается в неприятную реальность: у 1С-ника прав на сервер СУБД чаще всего нет, а у админа нет времени разбираться, что именно ему смотреть. Разговор превращается в "посмотри там, что с блокировками", и возвращается ответ "всё нормально". Поэтому просить надо конкретно.

Со стороны СУБД источников два, и путать их дорого.

  • sys.dm_os_wait_stats - накопительная статистика с момента запуска службы. Один снимок отсюда показывает среднее за месяцы работы, и вечерний эффект в нём утонет вместе с ночными бэкапами и дневным затишьем. Пользы от неё ровно столько, сколько от разницы двух снимков: сняли в 18:30, сняли в 20:00, вычли.
  • sys.dm_os_waiting_tasks - кто ждёт прямо сейчас. Вот это и нужно в пик: три-четыре снимка с интервалом в минуту в тот самый час, когда кассы залипают.

Что означают типы ожиданий, которые вы там увидите:

  • CXPACKET и CXCONSUMER - обмен между потоками параллельного плана. Сами по себе не диагноз: параллелизм на то и параллелизм, потоки друг друга ждут по определению.
  • THREADPOOL - вот это диагноз. Запросу не досталось рабочего потока, он стоит в очереди за ресурсом сервера. Именно это ожидание отличает "у нас работает параллелизм" от "у нас параллелизм съел сервер".
  • LCK_M_ с любым суффиксом - настоящие блокировки. Их отсутствие в пик и есть тот самый ноль из заголовка.
  • PAGEIOLATCH_ - ждём диск, разговор совсем другой.
  • SOS_SCHEDULER_YIELD - упёрлись в процессор физически, а не в раздачу потоков.

Диагноз "перегретый параллелизм" ставится по THREADPOOL вместе с CX-ожиданиями. Диагноз "блокировки" - только по LCK_M_. Если в пик доминируют первые, а вторых нет, войну с проведением можно отменять, не дожидаясь конца квартала.

Проверка со стороны 1С: пятнадцать минут и ни одного права на SQL

Есть способ дешевле, и он целиком внутри платформы. Управляемые блокировки 1С живут не в СУБД, а в менеджере блокировок кластера, и в ожиданиях SQL Server их не видно вовсе. Зато они видны в технологическом журнале, и включается это одним файлом logcfg.xml.

Смотреть надо три события:

  • TLOCK - установка управляемой блокировки;
  • TTIMEOUT - истёк таймаут ожидания на блокировке, то есть кто-то реально кого-то ждал и не дождался;
  • TDEADLOCK - взаимоблокировка.

Логика простая до неприличия. Тормоза в пик есть, а TTIMEOUT и TDEADLOCK за этот час нет ни одного - значит на уровне платформы никто никого не ждал, и причина ниже, на стороне СУБД или железа. Это ровно тот аргумент, которого не хватает в разговоре "нам кажется, это блокировки": не мнение против мнения, а пустая выборка за час пика.

Вторая половина замера берётся из журнала регистрации: длительность одной и той же операции вечером и днём. Если закрытие смены днём укладывается в секунды, а вечером растягивается в минуты при том же объёме документов, у вас есть число, с которым можно идти к админу. Без числа разговор всегда заканчивается фразой "ну у нас всё в норме".

Итог этой части в одну строку: просить админа надо не "посмотреть блокировки", а снять sys.dm_os_waiting_tasks трижды в час пика и один раз в спокойный час. Разница между двумя выборками отвечает на вопрос быстрее, чем месяц переписки.

Вместо эпилога

Эта история - про цену готовых объяснений. «Вечером тормозит - значит, блокировки» звучало настолько убедительно, что система годами жила с диагнозом, который никто не проверял. А проверка стоила один час снятия ожиданий в пик.

Формальные признаки врут, готовые объяснения врут ещё увереннее. Измеряйте - особенно тогда, когда все вокруг уже «знают», в чём дело. Именно в этот момент проверка дешевле всего и нужнее всего.

Если у вас похожая картина - вечерние деградации, «блокировки», которые никто не видел живьём, общий инстанс с соседями - начните с пункта 1 чек-листа. А своими историями про заводские настройки, дожившие до продакшена, делитесь в комментариях: подозреваю, наша - далеко не рекордная.

 

Другие наши инструменты диагностики 1С:

Вступайте в нашу телеграмм-группу Инфостарт

MAXDOP cost threshold for parallelism производительность блокировки ожидания MS SQL Server HighLoad

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

Инструментарий разработчика Разработка Администрирование веб-серверов Системный администратор Разработчик Аналитик Руководитель проекта 1С 8.3 Платные (руб)

Analyzer 1C сводит выгрузку 1С — основную конфигурацию и все расширения — в единый граф знаний. Любой запрос по связям за доли секунды, с пометками «Доб.» / «Заимств.» / «Переопределено». Новое в 2.0 — обновление поставки: сравнение и объединение версий деревом «как в Конфигураторе» с выгрузкой плана решений; поиск конфликтов из-за перехватов расширений и висячих ссылок; загрузка из бинарных .cf/.cfe; циклические зависимости. Плюс анализ влияния, запросы BSL, роли и RLS, граф вызовов. Минута на развёртывание через Docker без необходимости подключения к Интернет. Любая 1С:Предприятие 8.3+.

14000 руб.

17.04.2026    14303    54    62    

66

Разработка Инструменты администратора БД Администрирование веб-серверов Администрирование Разработчик 1C:ERP Платные (руб)

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

90000 руб.

13.05.2026    1986    2    0    

5

Сервера Системный администратор Разработчик 1С 8.3 Абонемент ($m)

Два калькулятора расчета железа (процессоры, память, диск) в зависимости от количества пользователей и размера базы для разделенных и совмещенных серверов 1С и СУБД, а также расчета терминального сервера. Описаны формулы расчета и обоснования выбора.

1 стартмани

16.02.2026    8981    127    sapervodichka    31    

93

HighLoad оптимизация Разработчик 1С 8.3 1С:ERP Управление предприятием 2 Бесплатно (free)

Использование оператора «В» для полей или данных составного типа (например, Регистратор) может приводить к неочевидным проблемам.

10.11.2025    15339    ivanov660    48    

57

Администрирование веб-серверов Сервера Нейросети Разработчик Платные (руб)

Сервер поиска по метаданным и поиска по коду, Сервер экспорта и поиска по документации, Сервер синтаксической проверки кода

17.06.2025    17039    0    Infostart    20    

113

HighLoad оптимизация Разработчик 1С:Предприятие 8 1C:ERP Бесплатно (free)

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

18.02.2025    16146    ivanov660    39    

62

Сервера Системный администратор Бесплатно (free)

На первый взгляд, добавление второго сервера в кластер 1С не должно вызывать проблем – все просто должно работать. Но на практике дело обстоит иначе. Несмотря на то, что все действительно работает, многие при этом сталкиваются с трудностями. Расскажем, когда нужно задуматься о втором сервере 1С в кластере, какие особенности работы второго сервиса с файлами и сервисами, и какие настройки ТНФ можно сделать для лицензий ПРОФ и КОРП.

31.10.2024    36821    a.doroshkevich    23    

89
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. paulwist 29.07.26 08:39 Сейчас в теме
Хорошая статья, без воды!

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


Из каких соображений порог был изменен на 50, а не на 100 или 38, чем руководствовались??
Vladimir-R; +1 – Ответить
2. nedomolkov.ivan 269 29.07.26 11:08 Сейчас в теме
(1)
времени

Порог — не точная константа, а граница между двумя популяциями запросов. Перед изменением посмотрели распределение стоимостей планов в кэше: основная масса OLTP-запросов (кассовые операции, проведение) — стоимость до ~30, тяжёлые отчёты — от 150 и выше, между ними разрыв. 50 — круглое значение внутри этого разрыва: OLTP гарантированно уходит в последовательные планы, отчёты остаются параллельными.

38 дало бы тот же эффект — внутри разрыва точное число роли не играет. 100 не взяли, чтобы часть «средних» запросов на границе тоже осталась последовательной при вечерней плотности. После изменения сверили картину ожиданий в пик: очередь за потоками ушла, планы отчётов не деградировали. Если бы не разгрузилось — двигали бы порог дальше по замерам, а не по справочникам.
3. paulwist 30.07.26 10:30 Сейчас в теме
Они ждали кое-чего другого: свободных потоков процессора.


Какие метрики смотрели и какие значения привели к выводу, что нет "свободных потоков"?

(2)
основная масса OLTP-запросов (кассовые операции, проведение) — стоимость до ~30


В процентном отношении меньше 30 попугаев сколько было запросов?

Например, в рабочих БД ЕРП за недельный интервал при cost threshold for parallelism = 5 имею ~ 300 параллельных планов, причем большинство из них 90% запросы а-ля

INSERT  INTO  #tt168 WITH(TABLOCK) (_Q_000_F_000_TYPE, _Q_000_F_000_RTRef,


(вполне объяснимо, почему они параллельные)

Не параллельных планов за недельный период, 10 000 шт.

Поэтому вопрос: сколько всего было параллельных планов в штуках и сколько стало??
4. redfred 30.07.26 13:06 Сейчас в теме
Даже тяжёлый запрос теперь ограничен восемью потоками — достаточно для ускорения, безопасно для соседей.


Строго говоря, там не совсем так. Maxdop ограничивает не весь запрос, а одну ветвь исполнения. Бывает, что в запросе одновременно выполняется N ветвей, тогда занимается N x maxdop потоков. Как-то сталкивался с тем, что при maxdop 8 очень тяжелый аналитический запрос выполнялся в 100+ потоков одновременно
Для отправки сообщения требуется регистрация/авторизация