Вопрос о том, как система ведет себя при массовой обработке данных, является одним из ключевых для понимания стабильности и целостности информационной базы. Представим ситуацию: вы запустили процесс перепроведения документов за длительный период, например за 10 дней. Процесс идет успешно, но на шестом дне происходит сбой — выключается электричество, обрывается сессия или пользователь нажимает комбинацию клавиш Ctrl+Break. Что произойдет с теми документами, которые уже успели обработаться? Останутся ли они проведенными или система «откатит» базу к исходному состоянию? Давайте разберем этот механизм подробно.
Разберем, как именно работает стандартная обработка «Проведение документов» (которую можно найти в меню «Операции»). Нам важно понимать, что платформа 1С:Предприятие 8 при выполнении групповых операций придерживается принципа атомарности на уровне каждого отдельного объекта, а не всей выборки в целом.
Проанализируем алгоритм работы системы по шагам:
ПередЗаписью, ОбработкаПроведения и т.д.).Таким образом, если вы прервали процесс на шестом дне, документы за первые пять дней уже прошли этап фиксации транзакции. Их данные окончательно записаны в базу данных. Откат этих документов невозможен, так как каждая транзакция была независимой и уже завершена.
Рассмотрим ситуацию в точке «разрыва». Когда выполнение прерывается на конкретном документе:
Часто возникает вопрос: почему бы не объединить все проведение в одну гигантскую транзакцию, чтобы гарантировать, что либо проведется всё, либо ничего? Давайте выясним причины, по которым разработчики платформы отказались от такого подхода.
1. Блокировки таблиц базы данных. Это самая критичная причина. Во время активной транзакции система накладывает блокировки на записи в таблицах. Если запустить проведение тысячи документов в одной транзакции, будут заблокированы таблицы остатков, взаиморасчетов и оборотов на все время выполнения процесса (которое может исчисляться часами). В это время ни один другой пользователь не сможет выписать накладную или принять оплату, так как система будет ждать завершения глобальной транзакции. Это парализовало бы работу любого предприятия.
2. Переполнение лога транзакций СУБД. Каждая операция внутри транзакции записывается в специальный журнал (Transaction Log) в SQL Server или PostgreSQL. При проведении огромного массива данных в одной транзакции объем этого лога может вырасти до критических размеров, что приведет к остановке всей СУБД из-за нехватки дискового пространства.
3. Риск потери результатов работы. Представим, что вы проводите 10 000 документов. На 9 999-м документе возникает ошибка (например, не хватило остатка на складе). Если бы всё шло в одной транзакции, система откатила бы изменения по всем 9 999 документам. В итоге многочасовая работа сервера была бы потрачена впустую. В текущей же реализации вы получите 9 998 успешно проведенных документов и одну ошибку, которую легко исправить.
В типовых интерфейсах проведения документов часто встречается флажок «Останавливать при ошибке». Разберем, на что он влияет:
Если вы пишете собственную обработку для проведения документов, помните, что вы сами управляете транзакционностью. Рассмотрим пример кода, где разработчик совершает ошибку, объединяя всё в одну транзакцию:
// ОПАСНЫЙ ПРИМЕР: Все документы в одной транзакции
НачатьТранзакцию();
Пока ВыборкаДокументов.Следующий() Цикл
ОбъектДокумент = ВыборкаДокументов.Ссылка.ПолучитьОбъект();
Если Не ОбъектДокумент.Записать(РежимЗаписиДокумента.Проведение) Тогда
// Если здесь произойдет ошибка, то придется откатывать всё
КонецЕсли;
КонецЦикла;
ЗафиксироватьТранзакцию();
Правильный подход при разработке массовых обработок — выполнять транзакцию внутри цикла, либо полагаться на стандартный механизм метода Записать(РежимЗаписиДокумента.Проведение), который сам открывает и закрывает транзакцию для каждого объекта. Проанализируем более безопасный вариант:
// ПРАВИЛЬНЫЙ ПРИМЕР: Транзакция на каждый документ (автоматически)
Пока ВыборкаДокументов.Следующий() Цикл
Попытка
ОбъектДокумент = ВыборкаДокументов.Ссылка.ПолучитьОбъект();
ОбъектДокумент.Записать(РежимЗаписиДокумента.Проведение);
Исключение
Сообщить("Ошибка проведения документа: " + ВыборкаДокументов.Ссылка);
КонецПопытки;
КонецЦикла;
Мы выяснили, что при использовании стандартных инструментов 1С для группового проведения документов вы можете быть спокойны за уже обработанные данные. Система фиксирует результат работы по каждому документу мгновенно. Это обеспечивает баланс между производительностью (отсутствие длительных блокировок) и надежностью (сохранение промежуточных результатов). Если процесс прервется, вам достаточно будет просто перезапустить проведение с того момента (или даты), на котором произошла остановка.