Почему не работают блокировки в регистре сведений при проведении документа?

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

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

Разбор архитектурной ошибки: вложенные транзакции

Основная причина проблем заключается в непонимании того, как платформа 1С управляет транзакциями. Важно помнить следующее:

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

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

Почему управляемые блокировки «не срабатывают»?

Проанализируем механику работы блокировок. БлокировкаДанных — это механизм, работающий на уровне сервера 1С. Он «сообщает» другим сеансам, что ресурс занят. Однако:

  1. Если другой процесс не использует аналогичный механизм БлокировкаДанных, он может попытаться записать данные, что приведет к конфликту уже на уровне СУБД.
  2. Блокировка будет эффективна только в том случае, если она установлена до момента чтения данных из регистра.
  3. Использование ЗаблокироватьДанныеДляРедактирования не имеет отношения к транзакционным блокировкам, так как это объектный механизм, предназначенный для блокировки формы или элемента справочника, а не для синхронизации записей в регистре.

Шаг 1: Правильный алгоритм работы с регистром

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

  1. Откажитесь от явного вызова НачатьТранзакцию() в подписке. Позвольте платформе самой управлять транзакцией проведения.
  2. Используйте РегистрСведенийНаборЗаписей для чтения и изменения данных. Это позволит вам считать текущее состояние, модифицировать его в памяти и записать одним пакетом.
  3. Устанавливайте блокировку перед выполнением запроса к регистру.

Пример корректного кода для установки блокировки и работы с данными:


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

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

// Модифицируем данные внутри набора
Для Каждого Запись Из НаборЗаписей Цикл
    // Логика пересчета цепочки
    Запись.ПолеСчетчик = ...;
КонецЦикла;

// Записываем набор, транзакция проведения сама зафиксирует результат
НаборЗаписей.Записать();

Шаг 2: Устранение «исчезновения» записей

Записи «теряются» из-за того, что при уровне изоляции Read Committed другие сеансы не видят ваших незафиксированных изменений. Если два документа проводятся одновременно, каждый из них читает состояние регистра «как есть», не видя изменений коллеги.

Решение:

Если задача подразумевает выстраивание жесткой последовательности (например, партионный учет или сквозная нумерация), рассмотрите следующие архитектурные решения:

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

← На главную