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