Как правильно установить управляемую блокировку при использовании «новой» методики списания остатков?

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

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

В чем заключается суть «новой» методики проведения

Для начала вспомним, чем «новая» методика отличается от «старой» (традиционной). В традиционной методике мы сначала устанавливаем блокировки, затем считываем текущие остатки, проверяем их, и только если товара достаточно — формируем движения и записываем их. Это создает длинную транзакцию, в которой данные заблокированы на протяжении всего процесса.

Проанализируем «новую» методику: здесь логика инвертирована. Мы сначала записываем движения документа «вслепую» (даже если товара может не хватать), а затем одним запросом считываем получившиеся остатки. Если после нашей записи остаток ушел в минус — мы отменяем транзакцию. Такой подход сокращает время удержания блокировок и повышает параллельность работы пользователей. Однако, чтобы этот механизм работал корректно, нам необходимо гарантировать, что в момент проверки остатков данные не будут изменены другой параллельной транзакцией. Именно для этого используется свойство БлокироватьДляИзменения.

Разбор правильной последовательности действий

Рассмотрим основной вопрос: важен ли порядок установки флага блокировки и записи набора записей? Ответ однозначный — порядок критически важен.

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

Правильный алгоритм в процедуре ОбработкаПроведения выглядит следующим образом:

  1. Подготавливаем движения (формируем таблицу записей в памяти).
  2. Устанавливаем Движения.ИмяРегистра.БлокироватьДляИзменения = Истина;
  3. Вызываем Движения.ИмяРегистра.Записать();
  4. Выполняем запрос к таблице итогов регистра для контроля отрицательных остатков.

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


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

// 2. Установка инструкции блокировки
Движения.ОстаткиНоменклатуры.БлокироватьДляИзменения = Истина;

// 3. Фиксация движений в базе данных с наложением блокировок
Движения.ОстаткиНоменклатуры.Записать();

// 4. Контроль остатков (выполняется после записи)
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Номенклатура, КоличествоОстаток ИЗ РегистрНакопления.ОстаткиНоменклатуры.Остатки(...)";
// ... выполнение запроса и проверка на КоличествоОстаток < 0

Почему это работает именно так?

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

Однако при контроле остатков разделение итогов становится проблемой: вы не можете просто так прочитать остаток, так как он физически распределен по разным записям. Установка БлокироватьДляИзменения = Истина перед записью заставляет платформу временно «отключить» эффект разделения итогов для данной транзакции. Система накладывает управляемую блокировку на конкретные комбинации измерений (Товар + Склад), гарантируя, что после записи вы получите единственно верный и актуальный остаток, который никто не изменит, пока ваша транзакция не завершится.

Распространенные ошибки и их последствия

Рассмотрим подробнее, к чему приводит нарушение порядка кода:

Ошибка: Запись перед установкой флага


Движения.ОстаткиНоменклатуры.Записать(); 
Движения.ОстаткиНоменклатуры.БлокироватьДляИзменения = Истина; // Бессмысленно

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

Ошибка: Установка флага без последующей записи

Если вы просто установите флаг БлокироватьДляИзменения = Истина, но не вызовете Записать() (или не полагаетесь на автоматическую запись в конце процедуры), блокировка не будет выставлена в СУБД. Помните: установка свойства — это лишь подготовка параметров для метода Записать().

Взаимодействие с объектом «БлокировкаДанных»

Иногда возникает вопрос: нужно ли использовать объект БлокировкаДанных совместно со свойством БлокироватьДляИзменения? В рамках классической «новой» методики использования свойства набора записей достаточно. Оно более элегантно, так как платформа сама определяет, какие именно измерения (номенклатуру, склады) нужно заблокировать, исходя из состава набора записей. Вам не нужно вручную описывать пространство блокировок в объекте БлокировкаДанных, что снижает вероятность ошибки.

Однако стоит учитывать, что это свойство работает только в режиме управляемых блокировок. В устаревшем автоматическом режиме это свойство игнорируется, так как там блокировками управляет сама СУБД на уровне всей таблицы или страниц данных. Для наглядной проверки работы механизмов подойдет демо-база по управляемым блокировкам для подготовки к экзамену.

Заключение и рекомендации

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

Помните следующие правила:

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

← На главную