В процессе работы с типовыми и доработанными конфигурациями на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда при проведении документа или записи элемента справочника система выдает критическую ошибку: «Объект уже заблокирован». Особое коварство этой проблемы заключается в том, что она может возникать даже в тех случаях, когда документ не открыт у других пользователей, сеансы перезагружены, а сервер 1С был полностью перезапущен.
В данной статье мы разберем причины возникновения этой ошибки в общем модуле УправлениеСвойствами, проанализируем поведение платформы и найдем эффективные способы решения проблемы без изменения типовой конфигурации.
Проанализируем техническую сторону ошибки. Обычно в стеке вызовов фигурирует метод ЗаблокироватьДанныеДляРедактирования(). Ошибка возникает из-за того, что платформа пытается установить пессимистическую блокировку на объект, который в рамках текущего сеанса или транзакции уже помечен как заблокированный.
Рассмотрим типовой фрагмент кода, на котором происходит сбой:
// Общий модуль: УправлениеСвойствами.Модуль
Процедура ЗаблокироватьОбъект(ВладелецСвойствОбъект) Экспорт
// ... логика определения необходимости блокировки
ЗаблокироватьДанныеДляРедактирования(ВладелецСвойствОбъект.Ссылка);
КонецПроцедуры
Выясним причину, по которой стандартные действия (перезагрузка, очистка кэша) часто не помогают. Если ошибка воспроизводится на копии базы даже после переноса на другой сервер, значит, корень проблемы кроется либо в специфических данных конкретного объекта, либо в логической петле кода конфигурации.
Если проблема вызвана особенностями работы типового механизма в конкретном релизе (например, 8.3.12), лучшим решением будет использование расширения. Это позволит избежать снятия конфигурации с поддержки и решит проблему «здесь и сейчас».
Разберем по шагам, как модифицировать код. Нам необходимо обернуть вызов метода блокировки в конструкцию Попытка ... Исключение или предварительно проверять состояние объекта. Однако, так как метод ЗаблокироватьДанныеДляРедактирования не имеет встроенного метода проверки «заблокировано ли уже мной», мы используем безопасный перехват:
&Вместо("ЗаблокироватьДанныеДляРедактирования")
Процедура Ист_ЗаблокироватьДанныеДляРедактирования(Ссылка, ИдентификаторФормы = Неопределено, ЗаблокированныйОбъект = Неопределено)
Попытка
ПродолжитьВызов(Ссылка, ИдентификаторФормы, ЗаблокированныйОбъект);
Исключение
// Если объект уже заблокирован в этом же сеансе,
// просто игнорируем ошибку и продолжаем работу.
ЗаписьЖурналаРегистрации("БлокировкаДанных", УровеньЖурналаРегистрации.Предупреждение, , ,
"Объект уже был заблокирован: " + Ссылка);
КонецПопытки;
КонецПроцедуры
Такой подход позволяет программе проигнорировать повторную блокировку и успешно выполнить проведение документа.
Рассмотрим ситуацию, когда блокировка вызвана не ошибкой кода, а логикой взаимодействия объектов. Проанализируем ситуацию с помощью встроенного Замера производительности. Если в замере мы видим, что метод ЗаблокироватьДанныеДляРедактирования вызывается дважды для одной и той же ссылки в рамках одной цепочки вызовов, это свидетельствует о «двойной блокировке».
Для решения в этом случае можно попробовать принудительно освободить блокировку перед повторным вызовом (хотя это менее безопасно, чем первый способ):
РазблокироватьДанныеДляРедактирования(ВладелецСвойствОбъект.Ссылка);
ЗаблокироватьДанныеДляРедактирования(ВладелецСвойствОбъект.Ссылка);
Иногда ошибка «Объект уже заблокирован» является следствием некорректной работы кластера серверов. Выясним, на что стоит обратить внимание системному администратору:
_SystemSettings. В редких случаях в ней могут «зависать» записи о блокировках, которые платформа интерпретирует как активные.1C:Enterprise Server, перейдем в каталог srvinfo и удалим содержимое папок snccntx (данные сеансов) и reg_XXXX.Проанализируем влияние Регламентных заданий. Если в момент проведения документа запускается фоновое задание, которое обращается к регистру сведений ЗначенияСвойствОбъектов (связанному с владельцем свойств), оно может удерживать исключительную блокировку. Попробуйте временно отключить регламентные задания и повторить операцию.
Важный момент: Если вы используете платформу версии 8.3.12 или ниже, рассмотрите возможность обновления на более стабильные релизы (8.3.18 и выше), так как в старых версиях механизмы управления блокировками в управляемых формах имели ряд задокументированных ошибок, связанных именно с методом ЗаблокироватьДанныеДляРедактирования.
Подведем итог: наиболее быстрым и эффективным программным решением является создание Расширения, которое перехватывает ошибку блокировки в общем модуле. Это гарантирует стабильную работу пользователей без необходимости радикального изменения типовой конфигурации и длительного ожидания обновления от вендора.