К статье
Практический материал

Разработка и Конфигурация · 12 мин

Транзакции в 1С: что это и как с ними работать

Что такое транзакция в 1С, как работают НачатьТранзакцию и ЗафиксироватьТранзакцию, явные и неявные транзакции, ошибки и откат изменений.

Транзакция в 1С — это набор операций с базой данных, который выполняется как единое целое: либо применяются все изменения сразу, либо не применяется ни одно. Классический пример — проведение документа «Реализация товаров»: система должна списать товар со склада, сформировать проводки по бухгалтерскому учёту и записать задолженность покупателя. Если на середине операции произойдёт сбой, без транзакции часть данных запишется, а часть — нет, и учёт станет противоречивым.

Механизм транзакций реализован на двух уровнях. Платформа 1С сама оборачивает типовые операции (запись документа, проведение, обмен данными) в неявные транзакции, а разработчик может дополнительно управлять транзакциями явно — через методы встроенного языка. Понимание того, где транзакция начинается и заканчивается, критично для стабильной работы базы: ошибки в управлении транзакциями приводят к блокировкам, взаимоблокировкам и потере производительности.

Транзакции напрямую связаны с принципом целостности данных. Пока транзакция не зафиксирована, изменения видны только внутри неё и могут быть полностью отменены. После фиксации изменения становятся постоянными и доступны другим пользователям. Это базовый механизм, на котором построены проведение документов, обмены, загрузка данных и большинство регламентных операций.

Что такое транзакция простыми словами

Представьте перевод денег между двумя кассами: сумма должна уменьшиться в одной и увеличиться в другой. Если после списания из первой кассы произойдёт сбой, деньги «повиснут в воздухе». Транзакция решает эту проблему: обе операции объединяются, и при любой ошибке система возвращает данные в исходное состояние, как будто операции вообще не было.

В терминах баз данных транзакция обладает свойствами атомарности, согласованности, изолированности и долговечности (ACID). Атомарность — всё или ничего. Согласованность — данные не нарушают заданных правил. Изолированность — параллельные транзакции не мешают друг другу. Долговечность — зафиксированный результат не пропадёт даже при сбое сервера.

Неявные транзакции: что платформа делает сама

Большинство операций в 1С выполняется в транзакциях, которые платформа создаёт автоматически, без участия разработчика. Проведение документа — самый наглядный пример: запись самого документа и всех его движений по регистрам происходит в одной транзакции. Если при формировании движений возникнет исключение (например, контроль остатков выявил недостаток товара), документ не будет ни записан, ни проведён.

Неявные транзакции также создаются при интерактивной записи объекта из формы, при обмене данными через планы обмена, при групповом перепроведении документов. Это удобно: типовая логика уже защищена от частичной записи. Но важно понимать границы: если в обработчике «ПриЗаписи» вы программно изменяете другие объекты, они попадают в ту же транзакцию, и её длительность растёт.

Явные транзакции: управление из кода

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

НачатьТранзакцию();

Попытка

// операции с данными

ДокументОбъект.Записать();

РегистрМенеджер.ЗаписатьДанные();

ЗафиксироватьТранзакцию();

Исключение

ОтменитьТранзакцию();

ВызватьИсключение ОписаниеОшибки();

КонецПопытки;

Ключевые правила работы с явными транзакциями: вызовы должны быть парными — каждой «НачатьТранзакцию» соответствует либо фиксация, либо отмена; при возникновении исключения внутри транзакции её обязательно нужно отменить, иначе соединение останется в «подвешенном» состоянии; транзакции могут быть вложенными, но фактически вложенные вызовы только меняют счётчик, а реальная фиксация происходит на самом внешнем уровне.

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

Как безопасно обернуть операции в транзакцию
  1. 1
    Определите минимальный набор операций, которые должны выполниться атомарно — не включайте лишнее
  2. 2
    Вызовите НачатьТранзакцию() непосредственно перед первой операцией записи
  3. 3
    Выполните операции записи внутри блока Попытка
  4. 4
    Вызовите ЗафиксироватьТранзакцию() после последней операции
  5. 5
    В блоке Исключение вызовите ОтменитьТранзакцию() и пробросьте или запишите ошибку в журнал
  6. 6
    Проверьте, что нет путей выполнения кода, где транзакция остаётся незакрытой

Блокировки и конкуренция пользователей

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

Проблемы начинаются, когда транзакции пересекаются. Если пользователь А проводит документ, блокирующий остатки склада, а пользователь Б в это же время проводит другой документ по тому же складу, второй будет ждать освобождения блокировки. При взаимном ожидании (первый ждёт ресурс второго, а второй — первого) возникает взаимоблокировка, и СУБД принудительно откатывает одну из транзакций с ошибкой.

Практические меры против конфликтов: записывать объекты в едином упорядоченном порядке (например, всегда сначала шапку, потом регистры в одном и том же порядке), минимизировать время между началом транзакции и фиксацией, не выполнять внутри транзакции обращения к пользователю (вопросы, открытие форм) и к внешним системам.

Типичные ошибки при работе с транзакциями

Самая распространённая ошибка — непарное использование методов: транзакция начата, но из-за ветвления логики ни фиксация, ни откат не вызываются. В файловом режиме это может привести к зависанию записей, в клиент-серверном — к удержанию соединения и блокировок до тайм-аута.

Вторая группа ошибок — попытка зафиксировать транзакцию после исключения. Разработчик перехватывает ошибку в Попытка/Исключение, обрабатывает её и продолжает выполнение, а в конце вызывает ЗафиксироватьТранзакцию(). Платформа не позволит это сделать: после исключения транзакция помечена как испорченная и подлежит только откату.

Третья частая проблема — избыточная вложенность. Код вызывает процедуру, которая сама открывает транзакцию, а вызывающий код уже находится в транзакции. Формально это работает (вложенные вызовы учитываются счётчиком), но усложняет анализ: откат внешней транзакции отменит и результаты вложенной, что не всегда очевидно при чтении кода.

Типичные ошибки
01
Транзакция без парной отмены в ветке Исключение — соединение удерживает блокировки до тайм-аута
02
ЗафиксироватьТранзакцию() после перехваченного исключения — платформа выдаёт новую ошибку, данные всё равно не фиксируются
03
Диалог с пользователем внутри транзакции — блокировки держатся, пока пользователь не нажмёт кнопку
04
Запись десятков объектов в одной транзакции при массовой обработке — рост числа конфликтов; лучше транзакция на один объект
05
Чтение данных перед записью вне транзакции, а запись внутри — между чтением и записью данные могут изменить другие пользователи

Транзакции при массовой обработке данных

При загрузке или изменении большого числа объектов возникает дилемма: одна общая транзакция гарантирует целостность, но при ошибке на последнем элементе откатит всё, а длительные блокировки парализуют работу пользователей. Практика — транзакция на один объект или на небольшой пакет: каждый документ обрабатывается и фиксируется отдельно, ошибки по конкретным элементам собираются в протокол.

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

Маршрут решения

Как выбрать границу транзакции

Операции логически неделимы (документ + его движения + связанный справочник)Объединяйте в одну транзакцию — частичная запись недопустима
Массовая загрузка независимых объектовТранзакция на каждый объект, ошибки собирайте в протокол и продолжайте обработку
Длительный расчёт с записью результата в концеВыполняйте расчёт вне транзакции, открывайте её только на финальную запись
Нужно обратиться к веб-сервису и записать результатСначала получите данные от сервиса, потом открывайте транзакцию на запись

Как проверить, что транзакция работает правильно

Базовая проверка — тест на откат: смоделируйте ошибку в середине операции (например, временно вызовите исключение после первой записи) и убедитесь, что в базе не осталось ни одного из изменённых объектов. Если часть данных записалась — транзакция охватывает не все операции или где-то теряется её контекст.

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

Контрольные точки

Как проверить результат

Поведение при искусственной ошибке в середине операции
Норма

Все изменения откачены, в базе нет частично записанных данных

Тревожный признак

Часть объектов записана, часть нет — транзакция не охватывает все операции

Технологический журнал при параллельной работе пользователей
Норма

Нет событий взаимоблокировок, таймауты редки

Тревожный признак

Регулярные TDEADLOCK и жалобы пользователей на ошибки конфликта блокировок

Код процедуры
Норма

Каждой НачатьТранзакцию() соответствуют фиксация и отмена на всех ветках выполнения

Тревожный признак

Есть пути выполнения, где транзакция остаётся открытой

Частые вопросы о транзакциях в 1С

Чем транзакция отличается от блокировки?

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

Можно ли вложить одну транзакцию в другую?

Формально да — вызовы НачатьТранзакцию() могут быть вложенными, платформа ведёт счётчик. Но физически существует одна транзакция: внутренняя фиксация лишь уменьшает счётчик, а реальное применение изменений происходит при фиксации самого внешнего уровня. Откат внешней транзакции отменяет всё, включая результаты вложенных.

Что происходит с транзакцией при разрыве соединения с сервером?

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

Нужно ли вручную открывать транзакцию при проведении документа?

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

Почему возникает ошибка «Конфликт блокировок при выполнении транзакции»?

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

Откатываются ли движения регистров при отмене транзакции?

Да, если запись движений выполнялась внутри той же транзакции. Откат возвращает базу в состояние на момент начала транзакции: отменяются записи документов, движения по регистрам, изменения справочников — всё, что было изменено в её рамках.

Итог

Что важно запомнить

Транзакция гарантирует, что связанные изменения либо применятся целиком, либо не применятся вовсе. Платформа сама оборачивает запись и проведение в неявные транзакции; явное управление нужно для атомарной записи нескольких объектов. Держите транзакции короткими, всегда отменяйте их при исключении и никогда не вызывайте интерактивные диалоги и внешние сервисы внутри транзакции.