Как устранить ошибку конфликта блокировок и монопольного режима при обновлении информационной базы 1С?

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

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

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

Выясним причину конфликта блокировок и монопольного доступа

Проанализируем цепочку событий, зафиксированную в журнале регистрации при возникновении сбоя:

  1. Один из сеансов обновления переводит базу в монопольный режим для выполнения критической операции: признак монопольного доступа становится равным Истина.
  2. Параллельный сеанс или клиентское приложение пытается также запросить монопольный режим либо, наоборот, сбросить его в значение Ложь, получая системное исключение.
  3. Основной сеанс запускает фоновое задание через платформенный механизм ФоновыеЗадания.Выполнить или модуль ДлительныеОперации для распараллеливания тяжелой выборки.
  4. Фоновое задание стартует в отдельном сеансе, где монопольный режим платформы не наследуется. Метод УстановитьМонопольныйРежим(Истина) блокирует доступ исключительно для сеанса-инициатора, поэтому дочерний поток встречает блокировку или падает при попытке обратиться к данным.
  5. Параллельно открытый сеанс тонкого или толстого клиента по таймеру опрашивает сервер через механизм СерверныеОповещения. Попытка записи служебного набора записей завершается таймаутом ожидания на заблокированных ресурсах, и обновление аварийно прерывается.

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

Способ 1. Изменение режима выполнения проблемного обработчика

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

Посмотрим на пример переопределения свойства обработчика в модуле обновления (или через расширение конфигурации в процедуре ПриДобавленииОбработчиковОбновления):


// В процедуре регистрации обработчиков обновления
Обработчик = Обработчики.Добавить();
Обработчик.Версия = "3.3.1.58";
Обработчик.Процедура = "МойМодульОбновления.ОбработатьДанные";
// Переводим проблемную процедуру из монопольного или оперативного режима в отложенный
Обработчик.РежимВыполнения = "Отложенно";

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

Способ 2. Полная изоляция информационной базы в кластере серверов

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

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

После этого запустим обновление через командную строку в изолированном пакетном режиме без открытия интерактивного графического интерфейса:


1cv8.exe ENTERPRISE /S "Server1C\BaseName" /N "Administrator" /P "Pass" /UC "КодОбновления" /C "ЗапуститьОбновлениеИнформационнойБазы;ЗавершитьРаботуСистемы"

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

Способ 3. Проверка собственных подписок на события

Если в конфигурацию вносились доработки, проанализируем модуль собственных подписок на события (особенно перед/при записи объектов, проведении документов). Если внутри обработчиков подписок выполняется обращение к регистрам или проводкам, они могут конфликтовать с монопольными таблицами обновления.

Добавим в подозрительные подписки проверку на признак выполнения процедуры обновления:


Если ПараметрыСеанса.ВыполняетсяОбновлениеИБ Тогда
    // Пропускаем дополнительную логику и движения, 
    // чтобы не блокировать потоки обновления конфигурации
    Возврат;
КонецЕсли;

Способ 4. Ручной пошаговый запуск обработчиков

В критических случаях, когда между несколькими процедурами возникает взаимная блокировка (Deadlock), можно временно отключить автозапуск процедур обновления. С помощью расширения перенесем вызовы необходимых методов в отдельную служебную внешнюю обработку и выполним их последовательно в один поток под полными правами Администратора.

← На главную