1С «В данной транзакции уже происходили ошибки» для собеседований

от автора

Всем привет!

Я senior разработчик 1С, прошел много собеседований и почти на каждом спрашивают про транзакции. В процессе подготовки я понял что нормального сжатого материала по этой теме нет. Если вы решите погуглить то вам попадется куча обрывочных довольно нетривиальных статей и нужно потратить много времени разобраться в этом. Посему делюсь выжимкой знаний про то, что спрашивают на собесах и ответами на них.

P.S.: Здесь мы не будем разбирать другие вопросы, которые тоже очень часто любят спрашивать про транзакции — это ACID и уровни изоляции транзакций.

  1. Что такое транзакция в общем?

    Это принцип — выполнится «все или ничего». К примеру, в 1С это операции между конструкциями

    НачатьТранзакцию();//ЗафиксироватьТранзакцию();
  2. Явные / Неявные транзакции:

    Явные — через НачатьТранзакцию(), ЗафиксироватьТранзакцию()
    Неявные — к примеру, в модуле объекта справочника ПриЗаписи()

  3. Бывают ли вложенные транзакции?

    На уровне СУБД нет, на уровне кода 1С можно писать сколько угодно раз НачатьТранзакцию() (счетчик вложенности увеличивается) а потом столько же раз ЗафиксироватьТранзакцию() (счетчик вложенности уменьшается), НО на уровне СУБД при этом будет создана только одна транзакция и она будет завершена когда последняя ЗафиксироватьТранзакцию() (счетчик вложенности = 0) отработает.

  4. Что такое сломанная транзакция?

    Состояние, когда СУБД уже откатила транзакцию из‑за ошибки, но код приложения 1С продолжает выполняться, и любые дальнейшие обращения к БД приводят к ошибке «в данной транзакции уже происходили ошибки».

    Из кода 1С мы никак не можем понять что транзакция сломана, но есть костыль:

  5. Способы получения сломанной транзакции?

    Вариант 1: Ошибка при операции в базе данных

    Вариант 1: Ошибка при операции в базе данных

    ! Ошибка может быть и во вложенной неявной транзакции. К примеру, в модуле объекта справочника, который мы пытаемся записать в попытке.

    Вариант 2: через ОтменитьТранзакцию()

    Вариант 2: через ОтменитьТранзакцию()

    ! ОтменитьТранзакцию() это так же установка флага Отказ в Истина, допустим, при записи справочника.

  6. Когда мы НЕ получим сломанную транзакцию?

    Когда ошибка в Попытке/Исключении не будет связана с обращением к СУБД

  7. Стандарты разработки по написанию транзакций:

    НачатьТранзакцию();Попытка     // блокировки, чтение, запись      // …      ЗафиксироватьТранзакцию();Исключение     ОтменитьТранзакцию();     ВызватьИсключение; // если есть внешняя транзакцияКонецПопытки

    Полный код обработки:

Процедура СломаемТранзакциюВариант1()    НачатьТранзакцию();    Попытка    Запрос = Новый Запрос;    Запрос.Текст = "Выбрать 1/0";    Запрос.Выполнить();  Исключение  КонецПопытки;    Сообщить(ЭтаТранзакцияСломана()); //Да!    ЗафиксироватьТранзакцию();  КонецПроцедурыПроцедура СломаемТранзакциюВариант2()    НачатьТранзакцию();    Попытка    НачатьТранзакцию();    ОтменитьТранзакцию();  Исключение  КонецПопытки;    Сообщить(ЭтаТранзакцияСломана()); //Да!    ЗафиксироватьТранзакцию();  КонецПроцедурыПроцедура НеСломаемТранзакцию()    НачатьТранзакцию();    Попытка    а = Новый Структура;    б = а.НовоеПоле;  Исключение  КонецПопытки;    Сообщить(ЭтаТранзакцияСломана()); //Нет!      ЗафиксироватьТранзакцию();  КонецПроцедурыФункция ЭтаТранзакцияСломана()  Попытка    Запрос = Новый Запрос;    Запрос.Текст = "Выбрать 1";    Запрос.Выполнить();    Возврат Ложь;  Исключение    Возврат Истина;  КонецПопытки;  КонецФункции

ссылка на оригинал статьи https://habr.com/ru/articles/1028326/