Разработка и Конфигурация · 11 мин
Транзакции в 1С: что это и как с ними работать
Что такое транзакция в 1С, как она работает с СУБД, зачем нужны НачатьТранзакцию и ЗафиксироватьТранзакцию, типичные ошибки и блокировки.
Транзакция в 1С — это набор операций с базой данных, который выполняется либо целиком, либо не выполняется вообще. Если при проведении документа, записи справочника или пакетной обработке возникает ошибка, все изменения, сделанные внутри транзакции, откатываются, и база остаётся в том состоянии, в котором была до начала операции. Именно этот механизм защищает учётные данные от «половинчатых» записей: документ проведён, а движения по регистрам не записаны.
Понимание транзакций критично в двух ситуациях. Разработчику — чтобы корректно писать обработки, обмены и проведение документов, не создавая взаимоблокировок. Администратору — чтобы диагностировать ошибки «Конфликт блокировок» и «Транзакция отменена», которые пользователи видят при одновременной работе в базе.
В этой статье разберём, как устроены транзакции в платформе 1С, где они создаются автоматически, как управлять ими вручную в коде, какие ошибки встречаются чаще всего и как проверить, что механизм работает правильно.
Что такое транзакция простыми словами
Классический пример — проведение документа «Реализация товаров». При проведении система записывает сам документ, движения по регистру остатков товаров, движения по регистру продаж и, возможно, бухгалтерские проводки. Всё это — несколько физических операций записи в разные таблицы базы данных.
Если бы каждая запись сохранялась независимо, то сбой посередине (обрыв соединения, нехватка места, ошибка в коде) оставил бы базу в противоречивом состоянии: товар списан со склада, но продажа не зарегистрирована. Транзакция объединяет все эти записи в единое целое: либо зафиксировалось всё, либо ничего.
Это свойство называется атомарностью и является частью принципов ACID, которые поддерживают промышленные СУБД — MS SQL Server, PostgreSQL, Oracle, IBM Db2, с которыми работает 1С:Предприятие. Платформа 1С выступает посредником: ваш код на встроенном языке превращается в транзакции на уровне СУБД.
Где 1С создаёт транзакции автоматически
В большинстве сценариев разработчику не нужно открывать транзакцию вручную — платформа делает это сама в типовых точках записи данных. Важно знать эти точки, чтобы не вкладывать свои транзакции туда, где они уже есть.
- Проведение документа — вся обработка проведения и запись движений выполняются в одной транзакции.
- Запись объекта (документа, элемента справочника, набора записей регистра) методом Записать() — платформа открывает транзакцию на время записи.
- Удаление объектов, включая контроль ссылочной целостности.
- Обмен данными через планы обмена и типовые механизмы синхронизации.
Если внутри обработчика проведения возникает исключение и оно не перехвачено, платформа автоматически откатывает транзакцию — документ остаётся непроведённым, а движения не записываются. Именно поэтому вызов Отказ = Истина в обработчике — безопасный способ прервать проведение без побочных эффектов.
Ручное управление транзакциями в коде
Встроенный язык 1С предоставляет три метода для явной работы с транзакциями. Они нужны, когда одна логическая операция состоит из нескольких вызовов Записать() или Провести(), и все они должны быть атомарны.
НачатьТранзакцию();
Попытка
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
РегистрацияОбъект.Записать();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение ОписаниеОшибки();
КонецПопытки;
Правила, которые нужно соблюдать при ручном управлении:
- Каждой НачатьТранзакцию() должна соответствовать либо ЗафиксироватьТранзакцию(), либо ОтменитьТранзакцию(). «Потерянная» незакрытая транзакция держит блокировки до завершения сеанса.
- Блок Попытка...Исключение обязателен: без него при ошибке транзакция останется открытой.
- Нельзя начинать транзакцию внутри уже открытой транзакции на том же соединении — платформа выдаст ошибку. Вложенных транзакций в 1С нет.
- Транзакция должна быть как можно короче: чем дольше она открыта, тем дольше удерживаются блокировки и тем выше вероятность конфликтов с другими пользователями.
НачатьТранзакцию();
Попытка
ДокументОбъект.Записать();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ЗаписьЖурналаРегистрации("Загрузка", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
КонецПопытки;Блокировки и режимы управления
Транзакция неразрывно связана с блокировками: пока транзакция открыта, изменённые ею данные заблокированы для других сеансов. В клиент-серверном варианте 1С поддерживает два режима управления блокировками, который задаётся в свойствах конфигурации.
| Режим | Как работает | Когда применяется |
|---|---|---|
| Автоматический | Платформа сама ставит блокировки на уровне СУБД, часто избыточные (на всю таблицу) | Старые конфигурации, небольшие базы с низкой конкуренцией |
| Управляемый | Разработчик явно указывает, какие данные блокировать, через объект БлокировкаДанных | Нагруженные системы с одновременной работой многих пользователей |
| Смешанный (автоматический и управляемый) | Для каждого объекта метаданных режим выбирается отдельно | Переходный этап при переводе конфигурации на управляемый режим |
В управляемом режиме типичный приём — установить блокировку на диапазон данных до их чтения внутри транзакции. Это гарантирует, что между чтением остатков и их изменением другой сеанс не вмешается.
- 1Создайте объект: Блокировка = Новый БлокировкаДанных;
- 2Добавьте элемент: Элемент = Блокировка.Добавить("РегистрНакопления.ТоварыНаСкладах");
- 3Задайте отбор по измерениям, например по складу и номенклатуре
- 4Вызовите Блокировка.Заблокировать() внутри открытой транзакции
- 5После блокировки читайте данные и выполняйте запись, затем зафиксируйте транзакцию
Типичные ошибки и конфликты
Самая частая жалоба пользователей — сообщение «Конфликт блокировок при выполнении транзакции» или «Превышено время ожидания блокировки». Это означает, что два сеанса пытаются изменить одни и те же данные одновременно, и один из них не дождался освобождения ресурса.
Более тяжёлый случай — взаимоблокировка (deadlock): сеанс А держит ресурс 1 и ждёт ресурс 2, а сеанс Б держит ресурс 2 и ждёт ресурс 1. СУБД сама выбирает «жертву» и откатывает одну из транзакций. В коде такая ситуация возникает, когда разные процедуры записывают объекты в разном порядке.
Как диагностировать проблемы с транзакциями
Когда пользователи жалуются на конфликты блокировок, первичная информация есть в журнале регистрации: там фиксируются ошибки с указанием сеанса, объекта и текста ошибки. Для глубокого анализа используется технологический журнал — в нём события DBMSSQL/DBPOSTGRS (запросы к СУБД), TLOCK, TDEADLOCK и TTIMEOUT показывают, какие таблицы и в каком порядке блокировались.
На уровне СУБД администратор может посмотреть активные блокировки: в MS SQL Server — через представления sys.dm_tran_locks и sys.dm_exec_sessions, в PostgreSQL — через pg_locks и pg_stat_activity. Это позволяет найти сеанс-«владельца» долгой блокировки и понять, какая операция её удерживает.
Как проверить, что транзакция работает корректно
После исключения объект и все связанные движения отсутствуют в базе
Объект записан, а часть движений нет — транзакция не охватывала все операции
Между началом и фиксацией только операции с данными, доли секунды
Внутри транзакции запросы к внешним сервисам, циклы с паузами, диалоги
Ошибки блокировок единичны и связаны с реальной одновременной работой
Массовые конфликты в одном и том же месте кода — признак избыточных блокировок или долгих транзакций
Практические рекомендации
Выносите из транзакции всё, что не связано с изменением данных: подготовку таблиц значений, обращения к веб-сервисам, формирование файлов. Внутри транзакции должны остаться только чтение актуальных остатков (при необходимости — с блокировкой) и запись.
При пакетной обработке большого объёма данных не загоняйте всё в одну гигантскую транзакцию: это удерживает блокировки и раздувает журнал транзакций СУБД. Обрабатывайте данные порциями, фиксируя каждую порцию отдельно, и ведите журнал обработанных элементов, чтобы при сбое продолжить с места остановки.
При проектировании обменов и интеграций закладывайте идемпотентность: повторная загрузка того же пакета должна давать тот же результат. Тогда откат транзакции и повторная попытка не создадут дублей.
Если конфликты блокировок возникают при проведении документов по одному складу или контрагенту, частая причина — автоматический режим блокировок на регистрах. Перевод проблемных регистров в управляемый режим с точечной блокировкой по измерениям обычно снижает количество конфликтов без переписывания бизнес-логики.
Часто задаваемые вопросы
Чем транзакция в 1С отличается от транзакции в СУБД?
Транзакция в коде 1С — это логическая обёртка, которую платформа транслирует в транзакцию на уровне СУБД (BEGIN TRAN / COMMIT / ROLLBACK). Разработчик не работает с SQL напрямую, но физическая блокировка и фиксация происходят именно в базе данных.
Можно ли вкладывать одну транзакцию в другую?
Нет, вложенные транзакции во встроенном языке 1С не поддерживаются. Попытка вызвать НачатьТранзакцию() внутри уже открытой транзакции приведёт к ошибке. Если процедура может вызываться и внутри, и снаружи транзакции, управление транзакцией выносят на верхний уровень вызовов.
Что произойдёт, если забыть вызвать ЗафиксироватьТранзакцию?
Транзакция останется открытой до завершения сеанса или до явного отката. Всё это время удерживаемые ею блокировки будут мешать другим пользователям, а при завершении сеанса незафиксированные изменения будут отменены. Поэтому пару «начать — зафиксировать/отменить» всегда оборачивают в Попытка...Исключение.
Работают ли транзакции в файловой базе 1С?
Да, атомарность записи обеспечивается и в файловом варианте. Однако блокировки там накладываются на целые таблицы, поэтому одновременная запись разными пользователями сильно ограничена, а конфликты при активной работе проявляются чаще.
Как уменьшить число ошибок «Конфликт блокировок»?
Основные меры: сокращать длительность транзакций, переводить конфигурацию на управляемый режим блокировок, блокировать только нужные строки через отборы по измерениям, унифицировать порядок записи объектов в разных процедурах и при массовых операциях выполнять их порциями в нерабочее время.
Откатывается ли транзакция при нажатии «Отмена» пользователем?
Прерывание пользователем (Esc, закрытие сеанса) приводит к аварийному завершению выполнения кода, и открытая транзакция откатывается платформой автоматически. Данные в базе при этом остаются в согласованном состоянии.
Что важно запомнить
Транзакция обеспечивает атомарность: все операции внутри неё фиксируются вместе или откатываются вместе. Платформа сама открывает транзакции при записи и проведении, а ручное управление через НачатьТранзакцию/ЗафиксироватьТранзакцию/ОтменитьТранзакцию применяйте только для составных операций, всегда с блоком Попытка...Исключение. Держите транзакции короткими, блокируйте только нужные данные и записывайте объекты в едином порядке — это главная профилактика конфликтов и взаимоблокировок.