Продолжаем классифицировать ошибки, с которыми сталкивается пользователь при работе в 1С.

Сегодня – блокировки. Это, наверное, самый распространенный пласт ошибок. С точки зрения пользователя платформа 1С сообщает ему что-то маловразумительное про какие-то там конфликты блокировок, возможно, с набором каких-то символов. И после этого его операция прерывается.

А вот со стороны информационной системы нужно уметь чётко разделять эти самые блокировки на два лагеря – блокировки на сервере СУБД и блокировки на сервере 1С (= управляемые блокировки).

Ошибки по таймауту, связанные с конфликтами блокировок на СУБД

При возникновении конфликтов блокировок пользователи жалуются примерно одинаково – привычные операции начинают выполняться дольше обычного и могут сопровождаются всплывающими ошибками вида:

В тексте ошибки хорошо видно, что блокировка на уровне СУБД.

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

Две причины конфликтов блокировок:

  1. Одновременная работа пользователей с одним и тем же (часто избыточно большим) массивом данных. То есть, чем больше пользователей, тем больше вероятность нарваться на блокировку. А чем больше гранулярность блокировки, тем меньше пользователей будет висеть на ней.

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

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

Как увидеть sql-блокировки.

В Perfexpert есть для этого отдельный график SQL блокировок. Есть перевести линейку на один из пиков, то на панели сессий SQL выводится дерево блокировок, на котором видно кто, на каком ресурсе заблокировал остальных пользователей - см. рисунок ниже. Причем деревья блокировок могут быть весьма ветвистыми.

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

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

Табличные блокировки

Это самый высокий уровень эскалации – блокируется вся таблица. Обычно возникают при массовом изменении данных в таблице и при регламентном обслуживании базы данных (например, при пересчете индексов).

Как бороться

  1. Поскольку табличные блокировки часто связаны с регламентными заданиями по обслуживанию БД, то следует перенести регламент в период минимальной пользовательской активности – на ночь. Это уже снизит вероятность возникновения блокировок.

  2. Можно отключить эскалацию для части таблиц, которые чаще других попадают на табличные блокировки. Для этого в мониторинге есть возможность построить соответствующую статистику (за подробностями опять направлю в статью по блокировкам). Отключение эскалации незначительно повысит накладные расходы на обслуживание блокировок – память и диск, но не критично.

Страничные блокировки

Чаще всего MS SQL Server блокирует именно страницу данных таблицы размером 8 кБ. И если СУБД решает, что ей менее затратно заблокировать всю таблицу, то она накладывает блокировку на всю таблицу – получается случай из предыдущего пункта.

Возникают страничные блокировки обычно так же – при массовом изменении данных таблицы.

Как увидеть

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

Понятно, что делать Alter Index посреди рабочего дня нужно очень осторожно, но как иллюстрация примера этот случай подойдет.

Как бороться

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

Подробности отправляю смотреть опять в статью по блокировкам.

Ключевые блокировки

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

Как увидеть

Точно так же – в панели сессий SQL в дереве блокировок отображается ресурс блокировки KEY:

Как бороться

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

Ошибки по таймауту, связанные с конфликтами управляемых блокировок 1С

Управляемые блокировки реализуются средствами самой платформы 1С. Чтобы их установить необходимо явное на то указание в коде 1С – какие данные нужно заблокировать.

С помощью управляемых блокировок разработчик может довольно ловко управлять гранулярностью блокировки на уровне объектов 1С. Ведь СУБД знать ничего не знает ни про измерения в регистрах, ни про документы, ни про справочники. Для нее есть только таблица и строки. Соответственно, при проведении документов (читай при транзакции) в разных сессиях, разными пользователями СУБД может легко эскалировать блокировку на весь регистр вместо того, чтобы заблокировать строки по конкретным измерениям, например, по номенклатуре и складу. Кстати, эскалации может подвергнуться и управляемая блокировка. Менеджер блокировок 1С точно так же может решить, что чем блокировать 1000 раз по одной записи проще один раз заблокировать всё пространство (таблицу объекта, например, всё то же регистр). Так что внимательно смотрим свой код – что и как блокируем.

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

Как увидеть

В целом статистика по управляемым блокировкам может быть собрана в технологическом журнале 1С. Для этого в нём нужно включить сбор событий с типом TLOCK. Ну и дальше анализ журнала. Инструментов по анализу ТЖ придумано куча. Какие-то хороши и удобны, какие-то – весьма сомнительные. В Perfexpert для этой задачи есть, во-первых, инструмент который собирает информацию об управляемых блокировках непосредственно из консоли администрирования 1С и выводит ее в виде счетчика производительности и в виде дерева блокировок. А, во-вторых, есть интеграция с ТЖ и ЖР, где информация по событиям уже более полная и детальная.

Как бороться

Если в Perfepxert открыть ссылку в колонке Контекст (ТЖ), то откроется запись технологического журнала, соответствующей данной блокировке. Можно понять на чем возникла эта блокировка, в каком модуле.

Также можно получить полную статистику по блокировкам за интервал времени и понять из статистики на чём чаще всего возникают блокировки, в каких модулях. Например, приведенный в примере регион InfoRg8127.DIMS – на втором месте по популярности, а из Контекста можно увидеть в каких модулях накладывается блокировка.

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

Еще одна распространенная ошибка – установка блокировки не в том месте кода. Транзакция может быть длинной или даже распределенной (особенно в случае интеграционных действий). И пока в рамках транзакции идут тяжелые вычисления, выполняются запросы и записи в смежные базы данных, управляемая блокировка висит. Соответственно вероятность получить ошибку по таймауту будет очень высокой. Собственно, вывод простой – чем короче транзакция, тем меньше ожидание на блокировках. Следите за этим.

Ниже приведу реальный пример возникновения ошибки конфликта управляемых блокировок из-за длинной транзакции.

Ошибки по таймауту при долгом держании управляемых блокировок

Пример интересен тем, что связан вроде бы с достаточно типичной операцией пересчета итогов, но которая оказалась до безобразия долгой. При пересчете итогов за 1 месяц на пользователе, запустившим пересчет (на рисунке это [yg***], повисло куча заблокированных фоновых заданий [На****], и в конце концов он (пересчёт) не выполнился и вывалился по ошибке.

Поскольку мы изначально знали кто виновник блокировки всего регистра бухгалтерии, то анализ ТЖ не требовался.

Для пересчета итогов использовался метод ПересчитатьИтогиЗаПериод(ДатаНач, ДатаКон), но почему-то, несмотря на четко указанные даты, пересчет начинался каждый раз с начала времён и ничем хорошим не заканчивался. Про "начало времен" мы поняли, увидев дату среди тяжелых запросов пользователя [yg***] в трассе Reads:

Если интересно как удалось порешать эту задачу (хоть это и не относится напрямую к теме статьи), то мы предложили принудительно сдвинуть границу рассчитанных итогов на 1 января с помощью УстановитьМаксимальныйПериодРассчитанныхИтогов (ДатаКон) и потихоньку, месяц за месяцем, сдвигать ее вправо тем же методом. Сработало.

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

Продолжение следует…


Ссылки на остальные части Записок оптимизатора 1С:

  1. Записки оптимизатора 1С (ч.1). Странное поведение MS SQL Server 2019: длительные операции TRUNCATE

  2. Записки оптимизатора 1С (ч.2). Полнотекстовый индекс или как быстро искать по подстроке

  3. Записки оптимизатора 1С (ч.3). Распределенные взаимоблокировки в 1С системах

  4. Записки оптимизатора 1С (ч.4). Параллелизм в 1С, настройки, ожидания CXPACKET

  5. Записки оптимизатора 1С (ч.5). Ускорение RLS-запросов в 1С системах

  6. Записки оптимизатора 1С (ч.6). Логические блокировки MS SQL Server в 1С: Предприятие

  7. Записки оптимизатора 1С (ч.7). «Нелогичные» блокировки MS SQL для систем 1С предприятия

  8. Записки оптимизатора 1С (ч.8). Нагрузка на диски сервера БД при работе с 1С. Пора ли делать апгрейд?

  9. Записки оптимизатора 1С (ч.9). Влияние сетевых интерфейсов на производительность высоконагруженных ИТ-систем

  10. Записки оптимизатора 1С (ч.10): Как понять, что процессор — основная боль на вашем сервере MS SQL Server?

  11. Записки оптимизатора 1С (ч.11). Не всегда очевидные проблемы производительности на серверах 1С

  12. Записки оптимизатора 1С (ч.12).  СрезПоследних в 1C:Предприятие на PostgreSQL. Почему же так долго?

  13. Записки оптимизатора 1С (ч.13). Что не так в журнале регистрации 1С в формате SQLitе?

  14. Записки оптимизатора 1С (ч.14.1). Любите свою базу данных и не забывайте обслуживать

  15. Записки оптимизатора 1С (ч.14.2). Пересчет индексов на SSD-дисках. Делаем или игнорируем?

  16. Записки оптимизатора 1С (ч.14.3). Отличия в обслуживании статистик в MS SQL и в PostgreSQL

  17. Записки оптимизатора 1С (ч.15). Параллелизм запросов 1С в PostgreSQL

  18. Записки оптимизатора 1С (ч.16). Риски падения Postgres: потребление и высвобождение памяти процессами postgres

  19. Записки оптимизатора 1С(ч.17). Как избежать падения Postgres при большом потреблении памяти запросами

  20. Записки оптимизатора 1С (ч.18.1). Ошибки 1С в части производительности и стабильности ИС

  21. Записки оптимизатора 1С (ч.18.2). Ошибки 1С из-за конфликта блокировок

Комментарии (0)