Разработка и Конфигурация · 10 мин
Транзакции в 1С: когда использовать и для чего они нужны
Что такое транзакция в 1С, когда её применять в коде, как работают НачатьТранзакцию и ЗафиксироватьТранзакцию, типичные ошибки и вложенные транзакции.
Транзакция в 1С — это механизм, который гарантирует, что группа операций с базой данных будет выполнена либо целиком, либо не выполнится вообще. Если в середине обработки происходит ошибка, платформа откатывает все изменения, и база остаётся в согласованном состоянии. Без транзакций при сбое часть данных может записаться, а часть — нет, что приводит к «битым» документам, расхождениям в остатках и бухгалтерских ошибках.
Разработчик на платформе 1С:Предприятие сталкивается с транзакциями постоянно, даже если не пишет их явно: платформа сама оборачивает в транзакцию проведение документов, запись объектов и обмены данными. Понимание того, когда нужна явная транзакция, а когда она только вредит, отличает аккуратный код от источника трудноуловимых проблем с блокировками.
Что такое транзакция и как она работает в 1С
Транзакция — это последовательность операций чтения и записи, которую система управления базами данных рассматривает как неделимую единицу. У транзакции есть ключевые свойства: атомарность (всё или ничего), согласованность (данные не нарушают заданных правил), изоляция (параллельные процессы не видят незавершённые изменения) и надёжность (зафиксированный результат не теряется).
Во встроенном языке 1С транзакция управляется тремя методами глобального контекста: НачатьТранзакцию(), ЗафиксироватьТранзакцию() и ОтменитьТранзакцию(). Между началом и фиксацией размещается код, который изменяет данные. Если при выполнении возникает исключение, транзакция отменяется, и все сделанные внутри неё записи откатываются.
Типовой шаблон кода выглядит так:
НачатьТранзакцию();
Попытка
// операции записи
ДокументОбъект.Записать();
РегистрНаборЗаписей.Записать();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение ОписаниеОшибки();
КонецПопытки;
Когда транзакция нужна обязательно
Главный критерий прост: если логическая операция состоит из нескольких записей в базу, и частичное выполнение оставит данные в противоречивом состоянии — транзакция обязательна. Примеры из практики:
- создание документа и одновременная запись связанных записей в регистры сведений (например, статусы документа);
- перенос остатков между складами с записью двух наборов движений;
- массовая обработка, где каждая порция данных должна быть целостной;
- загрузка данных из файла или внешнего сервиса, когда «половина загруженного контрагента» недопустима;
- операции с деньгами и взаиморасчётами, где расхождение в одной записи ломает отчётность.
Классический пример — обмен данными. Если при загрузке пакета записалась шапка документа, но не записались табличная часть и движения, пользователь получит документ, который выглядит нормально, но искажает отчёты. Транзакция гарантирует: либо документ загрузился полностью, либо его нет вовсе.
Как выбрать действие
Когда транзакция не нужна или вредна
Одиночная запись объекта в 1С уже атомарна: платформа сама открывает и фиксирует транзакцию при вызове Записать(). Оборачивать одну запись в НачатьТранзакцию() бессмысленно — это лишь добавляет вложенность.
Вредна транзакция в нескольких случаях. Во-первых, длинные транзакции: пока транзакция открыта, она удерживает блокировки на затронутых данных, и другие пользователи ждут или получают ошибки блокировок. Обработка, которая в одной транзакции перепроводит тысячи документов, способна парализовать работу базы. Во-вторых, транзакции нельзя растягивать на интерактивные действия — нельзя начать транзакцию, показать пользователю диалог и ждать ответа: соединение с СУБД будет удерживаться всё это время.
Вложенные транзакции и особенности платформы
Платформа 1С поддерживает вызов НачатьТранзакцию() внутри уже открытой транзакции, но это не настоящие вложенные транзакции в терминах СУБД. Внутренние вызовы лишь увеличивают счётчик: реальная фиксация происходит только при закрытии самой внешней транзакции. Отмена внутренней транзакции откатывает всё, включая внешние изменения.
Практическое следствие: если ваша процедура может вызываться как самостоятельно, так и из кода, где транзакция уже открыта, она будет работать корректно в обоих случаях, но отмена внутри такой процедуры отменит и «чужие» изменения. Поэтому в библиотечных процедурах принято либо документировать требование к транзакционному контексту, либо проверять его через ТранзакцияАктивна().
Управляемые блокировки и транзакции
Транзакция гарантирует целостность, но не решает проблему конкурентного доступа. Если два пользователя одновременно списывают остаток одного товара, без блокировок оба могут прочитать одно и то же значение и записать неверный результат. Для этого в 1С используется объект БлокировкаДанных, который устанавливается внутри транзакции перед чтением изменяемых данных.
Правильный порядок: начать транзакцию, установить управляемую блокировку на нужные диапазоны данных, прочитать актуальные значения, выполнить изменения, зафиксировать. При отмене или фиксации транзакции блокировки снимаются автоматически. В файловом варианте базы и в режиме автоматических блокировок поведение отличается, но в клиент-серверном варианте с управляемым режимом (стандарт для современных конфигураций) явные блокировки — обязательная часть корректной работы с остатками.
- 1Вызовите НачатьТранзакцию()
- 2Создайте объект БлокировкаДанных и добавьте элементы на нужные регистры или объекты
- 3Вызовите Блокировка.Заблокировать()
- 4Прочитайте актуальные данные (остатки, статусы)
- 5Выполните проверки и запись
- 6Вызовите ЗафиксироватьТранзакцию()
- 7В блоке Исключение вызовите ОтменитьТранзакцию() и пробросьте ошибку дальше
Типичные ошибки при работе с транзакциями
Ошибки с транзакциями часто проявляются не сразу, а под нагрузкой или при редких сбоях, поэтому их сложно поймать при ручном тестировании. Знание типовых сценариев помогает избежать проблем на этапе написания кода.
Как проверить, что транзакция работает правильно
Проверка транзакционного кода строится на моделировании сбоя. Самый простой способ — временно вставить вызов исключения между записями внутри транзакции и убедиться, что после выполнения в базе не осталось ни одного из изменений. Если часть данных записалась — значит, где-то транзакция фиксируется раньше времени или записи выполняются вне её.
Дополнительно стоит проверить поведение под параллельной нагрузкой: запустить обработку в двух сеансах одновременно на одних и тех же данных. Корректный код либо дождётся снятия блокировки, либо выдаст понятную ошибку конфликта, но не запишет расхождения. В технологическом журнале и через консоль СУБД можно убедиться, что транзакции не висят открытыми дольше необходимого.
Как проверить результат
Ни одна из операций не записана, данные как до запуска
Часть записей сохранилась — транзакция фиксируется преждевременно
Второй сеанс ждёт или получает ошибку блокировки, данные согласованы
Оба сеанса записали данные с расхождениями
Транзакция живёт миллисекунды или секунды и содержит только запись
Транзакция открыта десятки секунд, внутри расчёты или обращения к сервисам
FAQ по транзакциям в 1С
Нужна ли транзакция при проведении документа?
Нет, ваша явная транзакция не требуется: платформа выполняет проведение документа в собственной транзакции. Если проведение завершается с ошибкой, все движения откатываются автоматически. Свою транзакцию имеет смысл открывать, только если вместе с проведением вы записываете дополнительные объекты, которые должны быть согласованы с документом.
Что произойдёт, если забыть вызвать ЗафиксироватьТранзакцию()?
Если код завершится без фиксации и без отмены, платформа при завершении вызова сервера отменит незакрытую транзакцию, и изменения не сохранятся. При этом в журнале может появиться ошибка о незафиксированной транзакции. Такой код нельзя оставлять: поведение зависит от контекста вызова и затрудняет диагностику.
Можно ли откатить только часть транзакции?
В 1С нет механизма точек сохранения (savepoints), доступного разработчику на встроенном языке. Отмена транзакции откатывает всё с момента начала внешней транзакции. Если нужно частичное сохранение, разбивайте работу на несколько независимых транзакций и обрабатывайте ошибки на уровне каждой порции.
Как обрабатывать ошибки блокировок при параллельной работе?
Ошибку конфликта блокировок следует перехватывать, отменять транзакцию и сообщать пользователю понятный текст, например, что данные редактируются другим сеансом. В пакетных обработках полезен повтор попытки через короткую паузу, но число повторов нужно ограничивать, чтобы не создать бесконечный цикл.
Влияет ли размер транзакции на производительность?
Да. Чем дольше открыта транзакция и чем больше данных она затрагивает, тем больше блокировок удерживается и тем выше нагрузка на журнал транзакций СУБД. Массовые обработки лучше делить на порции с фиксацией каждой порции, а все тяжёлые вычисления выполнять до открытия транзакции.
Чем транзакция отличается от блокировки?
Транзакция отвечает за целостность: все операции фиксируются или откатываются вместе. Блокировка отвечает за изоляцию от параллельных сеансов: она не даёт другим пользователям изменить или прочитать данные, с которыми вы работаете. Для корректной записи остатков обычно нужны обе: блокировка внутри транзакции.
Что важно запомнить
Явная транзакция нужна, когда несколько записей должны быть выполнены как единое целое. Держите транзакции короткими, не размещайте внутри них интерактив и долгие расчёты, всегда отменяйте транзакцию в обработчике исключения и сочетайте с управляемыми блокировками при работе с конкурентными данными.