Транзакционные блокировки 1С

Как понятно из названия, данный тип блокировок устанавливается только внутри транзакций, как явных, т.е.  открытых через метод НачатьТранзакцию() так и неявных (открытых автоматически при записи объектов).

Пример использования блокировки

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

  1. Информация о текущем остатке на складе;
  2. Информация о текущих ценах;
  3. Информация о количестве продаж;
  4. Информация о количестве закупок.

Курс 1С: Эксперт. Пример использования блокировки 1С

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

  1. Никто не внесет изменения об остатках, ценах, оборотах, пока вы выполняете обновление статистики;
  2. Никто не будет обновлять статистику одновременно с текущей транзакцией.

Для этого информация, которую вы прочитали об остатках, ценах и оборотах, никто не должен изменять, т.к. вы должны исключить проблему неповторяемого чтения. Данная проблема решается СУБД на уровне изоляции REPEATABLE READ, но в управляемом режиме управления блокировками, используемый уровень изоляции транзакций – READ COMMITIED (SNAPSHOT).

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

В данном случае, разработчик, явно устанавливает управляемую транзакционную блокировку (добавляет информацию о том, что ресурс захвачен) через конструкцию БлокировкаДанных.

БлокировкаРесурса = Новый БлокировкаДанных;

//… (описание ресурсов блокировки) ...

БлокировкаРесурса.Заблокировать();

В описании ресурсов, которые необходимо заблокировать, добавляются Элементы блокировки данных.

РН_Остатки              =      БлокировкаРесурса.Добавить(“РегистрНакопления.ОстаткиНаСкладах”);
РН_Остатки.Режим        =      РежимБлокировкиДанных.Исключительный;

// так для каждого ресурса, который мы хотим блокировать.
РН_Продажи              =      БлокировкаРесурса.Добавить(“РегистрНакопления.Продажи”);
РН_Продажи.Режим        =      РежимБлокировкиДанных.Исключительный;

РН_Закупки              =      БлокировкаРесурса.Добавить(“РегистрНакопления.Закупки ”);
РН_Закупки.Режим        =      РежимБлокировкиДанных.Исключительный;

РС_ЦеныНом              =      БлокировкаРесурса.Добавить(“РегистрСведений.ЦеныНоменклатуры”);
РН_ ЦеныНом.Режим       =      РежимБлокировкиДанных.Исключительный;

РС_Статистика           =      БлокировкаРесурса.Добавить(“РегистрСведений.СтатистикаНоменклатуры”);
РН_Статистика.Режим     =      РежимБлокировкиДанных.Исключительный;

Мы устанавливаем режим блокировки данных именно Исключительный (Х), потому что на уровне изоляции транзакций READ COMMITED (SNAPSHOT), управляемая транзакционная блокировка на чтение (S) снимается сразу же после чтения, а нам надо его блокировать ресурсы до конца транзакции (пока не завершим запись).

Инициализация блокируемых записей

Для того, чтобы указать записи таблицы, которые следует заблокировать для заданного ресурса, можно использовать несколько способов, в зависимости от ситуации. Для примера будем использовать ресурс блокировки «Справочник.Номенклатура», чтобы разобрать все возможные варианты:

Спр_Номенклатура        =      БлокировкаРесурса.Добавить(“Справочник.Номенклатура”);
Спр_Номенклатура.Режим  =      РежимБлокировкиДанных.Исключительный;

1. Блокировка конкретной ссылки

Если ресурс — это, например, «Справочник.Номенклатура», то мы можем заблокировать конкретный элемент справочника по ссылке, и никто не сможет его изменить этот элемент, пока мы обновляем статистику:

Спр_Номенклатура.УстановитьЗначение(“Ссылка”, НоменклатураСсылка);

2. Блокировка по реквизитам

Спр_Номенклатура.УстановитьЗначение(“Артикул”, АртикулНоменклатуры);

В данном случае, будут заблокированы все элементы справочника номенклатура, у которых Артикул = АртикулНоменклатуры.

(Для использования Артикула в качестве поля блокировки данных, необходимо добавить это поле в поля блокировки данных.

Такая возможность существует у всех объектов в 1С:

Курс 1С: Эксперт. Поле управляемой блокировки 1С
Поле управляемой блокировки 1С

3. Блокировка по измерениям

Для регистров можно указывать значения измерений (без дополнительных настроек) и реквизитов (аналогично реквизитам ссылочного типа из п. 2).

РН_Продажи.УстановитьЗначение(“Номенклатура”, НоменклатураСсылка);

4. Блокировка по значениям из списка

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

Тогда можно использовать такой метод:

РН_Продажи.ИсточникДанных = РезультатЗапроса;      // или  ТаблицаЗначений
РН_Продажи.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");
РН_Продажи.ИспользоватьИзИсточникаДанных("Поле", "Поле"); // Любая колонка запроса/Таблицы значений

Курс 1С: Эксперт. Управляемые блокировки 1С для запроса

Данная тема подробнее рассматривается в пакете видео-курса «Секреты 1С: Эксперта» Шаг 3. Занятие 09-02 Управление блокировками в 1С..
Константин Ефимов | 1С: Эксперт. Консультация по проектам 1С: Предприятие.

КОНСТАНТИН ЕФИМОВ
Комментарии и вопросы