При переходе на новые релизы программных продуктов линейки ERP (ERP, Комплексная автоматизация, Управление торговлей версии 2.5) пользователи нередко сталкиваются с ошибкой: «Не удалось добавить запись в регистр очереди "ЗаданияКОтражениюСостоянияЗаказов" по причине: Конфликт блокировок при выполнении транзакции: Превышено максимальное время ожидания предоставления блокировки». Одновременно с этим в фоновых заданиях непрерывно висит выполнение метода ОтложенныеЗадания.ЗаданияКРаспределениюВзаиморасчетов. Разберем механику этой ошибки и рассмотрим практические пути ее решения.
Проанализируем природу возникновения проблемы. В типовых конфигурациях при проведении первичных документов система регистрирует необходимость допроведения или пересчета сопутствующих данных через механизм отложенных очередей. Пользовательский сеанс в транзакции пытается добавить запись в регистр сведений ЗаданияКОтражениюСостоянияЗаказов. В то же самое время активный фоновый обработчик выполняет метод ЗаданияКРаспределениюВзаиморасчетов.ВыполнитьОтложенноеРаспределениеВзаиморасчетов, считывает большие объемы данных, блокируя диапазоны ключей. Если фоновый процесс запущен практически непрерывно или обрабатывает гигантские порции, транзакции пользователей встают в очередь ожидания и падают по таймауту.
Выясним причину чрезмерной загрузки очередей. Если регламентная обработка захватывает слишком большой объем записей за одну итерацию или интервал ее перезапуска сведен к минимуму, фоновые задания начинают конкурировать с интерактивной работой пользователей. Посмотрим, как скорректировать размер порций и частоту запуска:
ВидыНеоперативныхЗаданий (если он доступен в прикладном решении) и уменьшим размер порции данных, обрабатываемых за один проход. Чем меньше порция, тем короче транзакция фонового задания и тем быстрее снимаются блокировки.ОтложенныеЗадания к процедуре инициализации очередей (например, ОчередиЗаданий). Найдем блок инициализации для регистра ЗаданияКРаспределениюВзаиморасчетов:
Если Параметры.Очередь = МетаРегистр.ЗаданияКРаспределениюВзаиморасчетов.Имя Тогда
// Задаем интервал обработки отличный от нуля, чтобы фоновое задание не стартовало непрерывно
Параметры.ИнтервалОбработки = 60; // пауза в секундах
КонецЕсли;
Разберем вариант устранения конфликта через типовые настройки учета без изменения исходного кода конфигурации:
Нередко после обновления в регистрах очередей скапливаются некорректные записи, на которых фоновые задания зацикливаются и бесконечно удерживают транзакции. Разберем по шагам, как выявить и устранить такие хвосты:
ЗаданияКОтражениюСостоянияЗаказов и ЗаданияКРаспределениюВзаиморасчетов. Если там скопились десятки или сотни тысяч строк, система физически не успевает освобождать блокировки.Рассмотрим аппаратную причину проблемы на стороне СУБД. При пакетном удалении или считывании более 5000 строк из таблицы регистра очереди MS SQL Server может применить механизм Lock Escalation, заменив построчные блокировки монопольной блокировкой всей таблицы (табличный X-lock). В этот момент ни один пользователь не может добавить ни одной строки в очередь.
Для предотвращения этой ситуации выполним следующие действия:
ИмяТаблицыСУБД = ПолучитьСтруктуруХраненияБазыДанных().Найти("РегистрСведений.ЗаданияКОтражениюСостоянияЗаказов", "Имя").ИмяТаблицыХранения;
ALTER TABLE dbo._InfoRgXXXXX SET (LOCK_ESCALATION = DISABLE);
Данная настройка запретит СУБД блокировать таблицу целиком при массовых операциях фонового задания, благодаря чему интерактивные пользователи смогут беспрепятственно вставлять новые записи в хвост очереди.