При переходе на новые релизы масштабных конфигураций (таких как 1С:ERP, 1С:Комплексная автоматизация или 1С:ERP. Управление холдингом) разработчики нередко сталкиваются с ситуацией, когда штатное обновление метаданных прошло успешно, однако на этапе выполнения обработчиков обновления данных система падает с ошибкой ожидания блокировок. При этом в журнале регистрации фиксируются попытки одновременного переключения монопольного режима разными сеансами или сбои в модуле СерверныеОповещения при вызове метода НаборЗаписей.Записать().
Разберем детально, почему возникает подобное поведение платформы, как локализовать сбой и какими способами можно успешно завершить обновление информационной базы.
Проанализируем цепочку событий, зафиксированную в журнале регистрации при возникновении сбоя:
ФоновыеЗадания.Выполнить или модуль ДлительныеОперации для распараллеливания тяжелой выборки.УстановитьМонопольныйРежим(Истина) блокирует доступ исключительно для сеанса-инициатора, поэтому дочерний поток встречает блокировку или падает при попытке обратиться к данным.СерверныеОповещения. Попытка записи служебного набора записей завершается таймаутом ожидания на заблокированных ресурсах, и обновление аварийно прерывается.Таким образом, корень проблемы заключается либо в ошибке алгоритма самого обработчика (сочетание монопольного режима с многопоточностью), либо во вмешательстве клиентских сессий и фоновых заданий в процесс обновления.
Если сбой вызывает конкретный шаг обновления данных, наиболее быстрое и эффективное решение — изменить параметры регистрации этого обработчика. Переведем его в режим отложенного выполнения, чтобы он не выполнялся монопольно при старте системы, а отработал в штатном фоновом режиме уже после запуска базы.
Посмотрим на пример переопределения свойства обработчика в модуле обновления (или через расширение конфигурации в процедуре ПриДобавленииОбработчиковОбновления):
// В процедуре регистрации обработчиков обновления
Обработчик = Обработчики.Добавить();
Обработчик.Версия = "3.3.1.58";
Обработчик.Процедура = "МойМодульОбновления.ОбработатьДанные";
// Переводим проблемную процедуру из монопольного или оперативного режима в отложенный
Обработчик.РежимВыполнения = "Отложенно";
В таком варианте конфигурация завершит основную монопольную фазу реструктуризации данных, система откроется для входа, а ресурсоемкая процедура отработает в очереди регламентного механизма БСП без конфликта за монопольный захват базы.
Чтобы исключить фоновые обращения механизмов серверных оповещений и регламентных задач, выполним полную изоляцию базы перед запуском обновления. Разберем по шагам:
Код разрешения (например, КодОбновления).ragent.После этого запустим обновление через командную строку в изолированном пакетном режиме без открытия интерактивного графического интерфейса:
1cv8.exe ENTERPRISE /S "Server1C\BaseName" /N "Administrator" /P "Pass" /UC "КодОбновления" /C "ЗапуститьОбновлениеИнформационнойБазы;ЗавершитьРаботуСистемы"
В пакетном режиме клиентское приложение не инициализирует форму мониторинга и таймеры опроса, благодаря чему строка СерверныеОповещения.Модуль(375):НаборЗаписей.Записать() не будет выполняться и конфликтовать с блокировками транзакций.
Если в конфигурацию вносились доработки, проанализируем модуль собственных подписок на события (особенно перед/при записи объектов, проведении документов). Если внутри обработчиков подписок выполняется обращение к регистрам или проводкам, они могут конфликтовать с монопольными таблицами обновления.
Добавим в подозрительные подписки проверку на признак выполнения процедуры обновления:
Если ПараметрыСеанса.ВыполняетсяОбновлениеИБ Тогда
// Пропускаем дополнительную логику и движения,
// чтобы не блокировать потоки обновления конфигурации
Возврат;
КонецЕсли;
В критических случаях, когда между несколькими процедурами возникает взаимная блокировка (Deadlock), можно временно отключить автозапуск процедур обновления. С помощью расширения перенесем вызовы необходимых методов в отдельную служебную внешнюю обработку и выполним их последовательно в один поток под полными правами Администратора.