Как устранить конфликт блокировок в регистре очереди ЗаданияКОтражениюСостоянияЗаказов?

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Управленческий учет IT и автоматизация бизнеса
← На главную

При переходе на новые релизы программных продуктов линейки ERP (ERP, Комплексная автоматизация, Управление торговлей версии 2.5) пользователи нередко сталкиваются с ошибкой: «Не удалось добавить запись в регистр очереди "ЗаданияКОтражениюСостоянияЗаказов" по причине: Конфликт блокировок при выполнении транзакции: Превышено максимальное время ожидания предоставления блокировки». Одновременно с этим в фоновых заданиях непрерывно висит выполнение метода ОтложенныеЗадания.ЗаданияКРаспределениюВзаиморасчетов. Разберем механику этой ошибки и рассмотрим практические пути ее решения.

Проанализируем природу возникновения проблемы. В типовых конфигурациях при проведении первичных документов система регистрирует необходимость допроведения или пересчета сопутствующих данных через механизм отложенных очередей. Пользовательский сеанс в транзакции пытается добавить запись в регистр сведений ЗаданияКОтражениюСостоянияЗаказов. В то же самое время активный фоновый обработчик выполняет метод ЗаданияКРаспределениюВзаиморасчетов.ВыполнитьОтложенноеРаспределениеВзаиморасчетов, считывает большие объемы данных, блокируя диапазоны ключей. Если фоновый процесс запущен практически непрерывно или обрабатывает гигантские порции, транзакции пользователей встают в очередь ожидания и падают по таймауту.

Решение 1. Оптимизация параметров отложенных заданий в кодовой базе

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

  1. Откроем справочник ВидыНеоперативныхЗаданий (если он доступен в прикладном решении) и уменьшим размер порции данных, обрабатываемых за один проход. Чем меньше порция, тем короче транзакция фонового задания и тем быстрее снимаются блокировки.
  2. Перейдем в общий модуль ОтложенныеЗадания к процедуре инициализации очередей (например, ОчередиЗаданий). Найдем блок инициализации для регистра ЗаданияКРаспределениюВзаиморасчетов:
    
    Если Параметры.Очередь = МетаРегистр.ЗаданияКРаспределениюВзаиморасчетов.Имя Тогда
        // Задаем интервал обработки отличный от нуля, чтобы фоновое задание не стартовало непрерывно
        Параметры.ИнтервалОбработки = 60; // пауза в секундах
    КонецЕсли;
    
    Установка ненулевого интервала позволяет разгрузить СУБД между порциями обработки и дает интерактивным пользователям окно для быстрой фиксации записей в очереди.

Решение 2. Изменение режима формирования взаиморасчетов в пользовательском интерфейсе

Разберем вариант устранения конфликта через типовые настройки учета без изменения исходного кода конфигурации:

  1. Перейдем в раздел НСИ и администрирование — Настройка НСИ и разделов — Казначейство и взаиморасчеты — Взаиморасчеты.
  2. Найдем параметр, определяющий режим формирования движений по взаиморасчетам.
  3. Переключим режим с «Оперативно при фиксации транзакций» на «Отложенно в фоновом задании» или «По расписанию». Это разорвет жесткую синхронную цепочку между интерактивным проведением документов пользователями и непрерывным запуском тяжелых фоновых процедур. Актуализация взаиморасчетов в таком случае будет выполняться регламентным заданием в наименее загруженные часы (например, в обед или ночью).

Решение 3. Проверка и очистка зависших очередей от битых данных

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

  1. Проанализируем количество записей в регистрах ЗаданияКОтражениюСостоянияЗаказов и ЗаданияКРаспределениюВзаиморасчетов. Если там скопились десятки или сотни тысяч строк, система физически не успевает освобождать блокировки.
  2. Проверим наличие строк с пустыми ведущими измерениями (пустая ссылка на заказ, пустой документ расчетов, пустая организация). Обработчик не может корректно завершить строку без аналитики, падает в ошибку и повторяет попытку заново.
  3. Выполним очистку битых записей. При критическом объеме зависшей очереди выполним ее полную очистку в монопольном режиме во внерабочее время, после чего восстановим актуальность взаиморасчетов штатным групповым пересчетом.
  4. Проверим служебного пользователя, под которым запускаются регламентные задания: убедимся, что на него не установлена дата запрета изменения данных. Если дата запрета активна, фоновое задание не сможет модифицировать исторические регистры, что вызовет бесконечный цикл обработки одной и той же неактуальной очереди.

Решение 4. Отключение эскалации блокировок на уровне СУБД (MS SQL Server)

Рассмотрим аппаратную причину проблемы на стороне СУБД. При пакетном удалении или считывании более 5000 строк из таблицы регистра очереди MS SQL Server может применить механизм Lock Escalation, заменив построчные блокировки монопольной блокировкой всей таблицы (табличный X-lock). В этот момент ни один пользователь не может добавить ни одной строки в очередь.

Для предотвращения этой ситуации выполним следующие действия:

  1. Определим физическое имя таблицы регистра в базе данных с помощью функции 1С:
    
    ИмяТаблицыСУБД = ПолучитьСтруктуруХраненияБазыДанных().Найти("РегистрСведений.ЗаданияКОтражениюСостоянияЗаказов", "Имя").ИмяТаблицыХранения;
    
  2. В среде управления MS SQL Server Management Studio выполним команду отключения эскалации для найденной таблицы: ALTER TABLE dbo._InfoRgXXXXX SET (LOCK_ESCALATION = DISABLE);

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

← На главную