Что происходит с транзакцией при ошибке записи нескольких документов в 1С
Что проверяют
Знаете ли вы, что платформа не откатывает транзакцию за вас при перехвате исключения, и понимаете ли, что вложенные транзакции в 1С не настоящие. Вопрос сразу отделяет тех, кто ставил Попытка вокруг записи по привычке, от тех, кто разбирался.
Как отвечать
Опишите механику. Каждый вызов Записать() открывает свою транзакцию, если внешней нет: упали на третьем документе, первые два остались в базе. Чтобы пачка была атомарной, её оборачивают явно:
НачатьТранзакцию();
Попытка
// запись документов
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;Дальше самое важное. Исключение внутри транзакции помечает её как испорченную. Если вы поймали ошибку и продолжили работу, не вызвав ОтменитьТранзакцию(), то на фиксации платформа сообщит, что в данной транзакции уже происходили ошибки, а до этого упадёт любая операция записи. Перехват без отката это не обработка ошибки, а её сокрытие.
Про вложенность скажите, что счётчик транзакций один на сеанс: реально фиксируется только внешняя, а отмена на любом уровне откатывает всё целиком. И про блокировки: чем длиннее транзакция, тем выше шанс взаимной блокировки, поэтому обращения к внешним системам и диалоги с пользователем выносят за её границы.
Где спотыкаются
Пишут перехват с сообщением об ошибке внутри транзакции и считают, что обработали её. Транзакция уже испорчена, и следующая же операция упадёт с текстом, никак не связанным с настоящей причиной, а искать будут в последнем изменённом коде.
Считают, что вложенная фиксация что-то фиксирует. Данные попадут в базу только при фиксации самой внешней транзакции, зато отмена изнутри вложенной снимет и то, что было сделано снаружи.
Думают, что до фиксации данные лежат где-то в памяти. Записи уходят в базу сразу, просто чужие сеансы их не видят. Блокировки при этом держатся уже сейчас, поэтому длинная транзакция подвешивает работу остальных пользователей задолго до того, как решится её судьба.