"Работа программиста 1С в аутсорсинге часто связана с собеседованиями. При смене работы также нужно пройти интервью, — рассказывает моя коллега Ирина, программист 1С. — Последнее время часто стали спрашивать о транзакциях в 1С и просить решить задачи, связанные с ними. В этой статье рассмотрим примеры задач, ошибки и правильные ответы".
Транзакция — это логическая группа операций, которую нужно выполнить целиком или не выполнять вовсе.
Простой пример из жизни.
Вы хотите записать несколько документов одновременно. Если запись одной из них упала, надо откатить все изменения, чтобы не получить получастичное состояние.
В 1С транзакции помогают обеспечить атомарность, целостность и согласованность данных.
Рассмотрим примеры.
1 пример
Процедура ПередЗаписью(Отказ) Если Согласовано Тогда ОбработатьПодчиненныеОбъекты(); КонецЕсли; СтатусВладельца = ЭтотОбъект.ВладелецОбъекта.Статус; КонецПроцедуры
Процедура ОбработатьПодчиненныеОбъекты() ЗависимыеОбъекты = ПолучитьЗависимыеОбъекты(); // Запишем все подчиненные объекты вместе в одной транзакции НачатьТранзакцию(); Попытка Для Каждого ЗависимыйОбъектСсылка Из ЗависимыеОбъекты Цикл ЗависимыйОбъект = ЗависимыйОбъектСсылка.ПолучитьОбъект(); ЗависимыйОбъект.Согласовано = Истина; ЗависимыйОбъект.Записать(); КонецЦикла; ЗафиксироватьТранзакцию(); Исключение ОтменитьТранзакцию(); КонецПопытки; КонецПроцедуры
Вас могут спросить: «Есть какие-то ошибки в коде. Если есть, как правильно написать код?»
Вроде бы все логично. Есть НачатьТранзакцию() , Зафиксировать() и при ошибке ОтменитьТранзакцию()
Или другой ответ: «Надо просто добавить Попытка...Исключение вокруг всего кода, и тогда всё будет Ок».
Ошибочный вариантов много, если не знать событийную модель и механизм блокировок.
Давайте разбираться:

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