Как исправить ошибку "Использование блокировки допустимо только внутри транзакции в режиме управляемых блокировок!" при обновлении 1С:Бухгалтерии?

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

При обновлении конфигурации 1С:Бухгалтерия (БП) с одной версии на другую, особенно если мы переходим с очень старых релизов, иногда могут возникать неожиданные ошибки. Одна из таких ошибок, с которой сталкиваются пользователи и программисты, звучит как: "Использование блокировки допустимо только внутри транзакции в режиме управляемых блокировок!". Это сообщение указывает на то, что программный код конфигурации пытается установить блокировку данных без предварительного открытия транзакции или делает это некорректно в режиме управляемых блокировок. Давайте подробнее разберем, почему возникает эта проблема и как ее можно эффективно решить.

Как правило, ошибка указывает на конкретный модуль и строку кода, например: {Документ.ИзменениеПараметровНачисленияАмортизацииОС.МодульМенеджера(566)}:Блокировка.Заблокировать;. Это означает, что процедура, отвечающая за изменение параметров начисления амортизации основных средств, столкнулась с проблемой при попытке заблокировать данные.

Анализируем причины возникновения ошибки

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

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

Пошаговое решение проблемы

Рассмотрим несколько подходов к решению данной проблемы, от наиболее простых до более сложных:

  1. Подготовка к обновлению: отключение регламентных и фоновых заданий и монопольный режим

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

    Почему это важно:

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

    Что мы делаем:

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

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

  2. Проверка незавершенных процедур обновления

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

    Что мы делаем:

    1. После возникновения ошибки и завершения процесса обновления (или если он завис) мы не отчаиваемся. В форме, где отображается информация о ходе обновления и статусе "Дополнительных процедур", обычно есть ссылка или кнопка для просмотра деталей.
    2. Нажимаем на эту ссылку (например, "Дополнительные процедуры завершились с ошибкой") или похожий элемент, который покажет нам список конкретных процедур, которые не завершились.
    3. Из открывшейся формы мы можем попытаться запустить незавершенные процедуры повторно. В некоторых случаях, если причиной был временный конфликт, повторный запуск в монопольном режиме после отключения регламентных заданий может помочь.
  3. Откат на бэкап и обновление через конфигуратор

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

    Что мы делаем:

    1. Восстанавливаем информационную базу из ранее сделанной резервной копии. Мы возвращаемся к состоянию базы *до* попытки обновления, когда она была в рабочем состоянии на старом релизе.
    2. Запускаем 1С в режиме "Конфигуратор".
    3. В конфигураторе переходим в меню "Конфигурация" -> "Открыть конфигурацию".
    4. Затем "Конфигурация" -> "Поддержка" -> "Обновить конфигурацию базы данных".
    5. Выбираем файл обновления (.cfu) или указываем путь к каталогу шаблонов.
    6. Проходим все шаги обновления, следуя указаниям мастера. Обновление через конфигуратор часто более стабильно, так как оно запускается в максимально "чистом" режиме и позволяет глубже контролировать процесс.

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

  4. Принудительный запуск транзакции в управляемом режиме (для опытных пользователей)

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

    Что мы делаем (концептуально):

    Данная ошибка прямо указывает на проблему в коде, который пытается использовать Блокировка.Заблокировать() вне явной транзакции. Если мы имеем дело с типовой конфигурацией, то прямое изменение кода не рекомендуется, так как оно усложнит дальнейшие обновления. Однако, если у нас есть возможность отладки или временного патча, мы можем обернуть проблемный участок кода в транзакцию.

    Например, если проблемный участок выглядит так:

    
    // Проблемный код, вызывающий ошибку
    Блокировка = Новый БлокировкаДанных;
    ЭлементБлокировки = Блокировка.Добавить("Документ.ИзменениеПараметровНачисленияАмортизацииОС");
    ЭлементБлокировки.УстановитьЗначение("Ссылка", Объект.Ссылка);
    Блокировка.Заблокировать();
    // Дальнейшие действия
    

    Мы могли бы попробовать обернуть это в транзакцию:

    
    НачатьТранзакцию();
    Попытка
        Блокировка = Новый БлокировкаДанных;
        ЭлементБлокировки = Блокировка.Добавить("Документ.ИзменениеПараметровНачисленияАмортизацииОС");
        ЭлементБлокировки.УстановитьЗначение("Ссылка", Объект.Ссылка);
        Блокировка.Заблокировать();
        // Дальнейшие действия
        ЗафиксироватьТранзакцию();
    Исключение
        ОтменитьТранзакцию();
        ВызватьИсключение;
    КонецПопытки;
    

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

  5. Поэтапное обновление для очень старых конфигураций

    Когда мы пытаемся обновить очень старый релиз (как в нашем случае, с сентября 2020 года), разница между версиями может быть настолько велика, что прямой переход вызывает множество проблем. В таких ситуациях может помочь поэтапное обновление. В качестве альтернативы можно использовать инструмент для прямого обновления со старых версий БП 3.0.

    Что мы делаем:

    1. Вместо того чтобы обновлять сразу до самой последней версии, мы находим промежуточные релизы. Например, если у нас версия N, а нужно обновиться до версии M, и M намного новее N, мы сначала обновляемся до N+x, затем до N+y, и так далее, пока не достигнем M.
    2. Каждый этап обновления должен завершаться успешно, включая выполнение всех дополнительных процедур.
    3. Этот метод занимает больше времени, но позволяет избежать критических ошибок, связанных с большими изменениями в структуре данных и коде между сильно разнесенными версиями.

Дополнительные рекомендации

Для более глубокого анализа и предотвращения подобных проблем в будущем, мы можем рассмотреть следующие меры:

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

← На главную