Как долго удерживается блокировка через метод Заблокировать и как правильно ею управлять

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

В процессе разработки на платформе «1С:Предприятие 8» часто возникает вопрос о механизмах защиты данных от одновременного изменения несколькими пользователями или процессами. Одним из таких инструментов является пессимистическая (объектная) блокировка, вызываемая методом Заблокировать(). Разберем детально, как работает этот механизм, сколько «живет» такая блокировка, если забыть вызвать Разблокировать(), и почему её использование в фоновых заданиях может быть не лучшей идеей.

Что такое объектная блокировка и как она работает

Проанализируем природу метода Заблокировать(). В отличие от управляемых или транзакционных блокировок СУБД, пессимистическая блокировка 1С реализуется полностью на уровне кластера серверов 1С. Рассмотрим её ключевые особенности:

  1. Независимость от транзакций: Метод Заблокировать() не требует открытия транзакции базы данных. Блокировка устанавливается в менеджере блокировок 1С и никак не отображается в системных таблицах SQL-сервера.
  2. Интерактивное назначение: В первую очередь этот механизм предназначен для интерактивной работы. Когда пользователь открывает форму объекта для редактирования, платформа может автоматически (или программно) заблокировать этот объект, чтобы другой пользователь при попытке редактирования получил сообщение «Объект заблокирован».
  3. Проверка при записи: Важно понимать, что если один сеанс вызвал Заблокировать() для конкретной ссылки, то другой сеанс не сможет выполнить метод Записать() для этого же объекта до тех пор, пока блокировка не будет снята.

Жизненный цикл блокировки: когда она исчезает?

Выясним причину, по которой блокировка может «висеть» в системе, и условия её автоматического снятия. Если разработчик вызвал Заблокировать(), но по какой-то причине не вызвал Разблокировать(), блокировка будет удерживаться в следующих случаях:

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

2. Жизнь сеанса пользователя. Проанализируем ситуацию с «выключением света» или аварийным завершением работы клиента. Пессимистические блокировки жестко привязаны к сеансу. Если сеанс завершается (нормально или аварийно), кластер серверов 1С очищает все связанные с ним объектные блокировки. Ребутать сервер для этого не требуется — достаточно того, что менеджер кластера зафиксирует разрыв соединения с клиентом или истечение времени «спящего» сеанса.

3. Явное снятие. Безусловно, самым правильным способом является вызов метода Разблокировать(). Рассмотрим, как это выглядит в коде:


ОбъектЗаказа = СсылкаНаЗаказ.ПолучитьОбъект();
Попытка
    ОбъектЗаказа.Заблокировать();
    // Выполняем необходимые действия с объектом
    ОбъектЗаказа.Записать();
    ОбъектЗаказа.Разблокировать();
Исключение
    // В случае ошибки блокировка может остаться, 
    // если объект не выйдет из области видимости.
    // Поэтому лучше вызвать разблокировку и здесь.
    Если ОбъектЗаказа.Заблокирован() Тогда
        ОбъектЗаказа.Разблокировать();
    КонецЕсли;
    ВызватьИсключение;
КонецПопытки;

Использование блокировок в фоновых заданиях: подводные камни

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

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

Рассмотрим альтернативный, более надежный подход с использованием БлокировкаДанных (управляемая блокировка):


Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("Документ.ЗаказПокупателя");
ЭлементБлокировки.УстановитьЗначение("Ссылка", СсылкаНаЗаказ);
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;

НачатьТранзакцию();
Попытка
    Блокировка.Заблокировать();
    // Теперь мы уверены, что в транзакции этот заказ наш
    // Выполняем обработку...
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    ЗаписатьЛогОшибок(ОписаниеОшибки());
КонецПопытки;

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

Рекомендации по безопасному программированию

Чтобы избежать проблем с «зависшими» блокировками и конфликтами доступа, придерживайтесь следующих правил:

  1. Минимизируйте время удержания. Блокируйте объект непосредственно перед выполнением критических действий и разблокируйте сразу после завершения.
  2. Используйте блоки Try...Finally. В языке 1С нет конструкции Попытка...Финализация, поэтому всегда используйте блок Исключение для корректной очистки ресурсов, включая снятие блокировок.
  3. Проверяйте состояние. Перед вызовом Разблокировать() полезно убедиться, что объект действительно заблокирован текущим сеансом, используя метод Заблокирован().
  4. Не путайте типы блокировок. Помните, что Заблокировать() защищает от изменения через объектную модель 1С, но не защищает от прямых запросов к базе или действий, не использующих метод Записать().

Подведем итог: объектная блокировка в 1С — это удобный инструмент для интерактивной работы, который «живет» ровно столько, сколько живет объект в памяти или сеанс пользователя. Однако для автоматизированных систем и фоновых заданий следует отдавать предпочтение транзакционным управляемым блокировкам, так как они более предсказуемы и производительны в высоконагруженных системах.

← На главную