Что происходит с движениями регистров в 1С, если в процессе проведения произошел отказ (Отказ = Истина)?

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

При разработке бизнес-логики проведения документов в платформе 1С:Предприятие начинающие разработчики часто задаются вопросом: если в процедуре ОбработкаПроведения часть движений уже сформирована, но затем сработало условие проверки и переменная Отказ получила значение Истина, останутся ли в базе данных уже созданные записи регистров?

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

Принцип неделимости: транзакция проведения

Главный механизм, обеспечивающий целостность данных в 1С — это транзакция СУБД. Запись и проведение любого документа всегда выполняются внутри единой транзакции.

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

Разберем типичный пример кода из процедуры проведения:


Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    
    // Формируем движение по регистру
    Движение = Движения.ОстаткиНоменклатуры.Добавить();
    Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
    Движение.Период = Дата;
    Движение.Номенклатура = СсылкаНаТовар;
    Движение.Количество = 10;
    
    // Выполняем какую-либо проверку остатков или бизнес-логики
    Если НедостаточноТовараНаСкладе Тогда
        Сообщить("Недостаточно товара на складе!");
        Отказ = Истина;
    КонецЕсли;

КонецПроцедуры

Проанализируем эту ситуацию: несмотря на то, что строчка создания движения находится выше проверки условия, при взведении Отказ = Истина СУБД выполняет полную отмену изменений (ROLLBACK). Ни документ, ни созданное движение по регистру ОстаткиНоменклатуры не будут сохранены в базе данных.

Восстановление прежних движений документа

Выясним, что происходит, если документ перепроводится не в первый раз. В свойствах конфигурации для документов обычно настроен автоматический режим удаления движений. В этом случае перед вызовом процедуры ОбработкаПроведения платформа очищает ранее записанные движения этого документа внутри транзакции.

Если во время повторного проведения взводится флаг Отказ = Истина, транзакция откатывается к своему первоначальному состоянию. Это означает, что старые движения документа будут полностью восстановлены в СУБД в том виде, в котором они существовали до начала перепроведения.

Вызов явной записи движений внутри процедуры

Посмотрим на более сложный сценарий, когда разработчик явно вызывал метод записи набора записей, например Движения.ИмяРегистра.Записать() или Движения.Записать() до того, как установить Отказ = Истина.

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

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

Состояние оперативной памяти и переменных

Важно различать данные в базе СУБД и данные в оперативной памяти сервера 1С:

  1. База данных СУБД: Все изменения таблиц полностью отменяются. Все физические записи удаляются/возвращаются к исходным значениям.
  2. Оперативная память (объект 1С): Откат транзакции не возвращает локальные переменные, коллекции и структуры данных к первичному состоянию. Однако платформа автоматически восстанавливает системный признак Проведен (он остается Ложь), а также сбрасывает ссылки и номера, если документ был новым.

Исключение из правил: Журнал регистрации

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

Если внутри процедуры ОбработкаПроведения вы выполняете запись в журнал регистрации, а затем транзакция отменяется с помощью Отказ = Истина или по причине аварийного исключения, событие в журнале регистрации все равно сохранится. Это позволяет фиксировать ошибки и причины отменяемых проведения документов.

Влияние логики отказа на блокировки СУБД и производительность

Проанализируем влияние размещения проверок на быстродействие системы. С момента открытия транзакции проведения и до момента ее закрытия (отката) платформа и СУБД удерживают блокировки на обновляемые таблицы.

Если проверка условий, приводящих к Отказ = Истина, выполняется в самом конце процедуры (после тяжелых запросов, чтения остатков и формирования тысяч строк движений), СУБД будет удерживать блокировки всё это время, замедляя работу других пользователей.

Рекомендуется придерживаться следующих правил при написании кода проведение:

  1. Выполнять первичные проверки реквизитов и бизнес-логики в самом начале процедуры ОбработкаПроведения до выполнения ресурсоемких запросов и алгоритмов.
  2. Если проверка показала невозможность проведения, сразу взводить Отказ = Истина и вызывать оператор Возврат.
  3. Помнить, что при любых ошибках и взведении отказа транзакция гарантирует полную безопасность и целостность данных в регистрах.
← На главную