
Сегодня поговорим о довольно частой ошибке. Не все специалисты знают, как ее пофиксить. Это статья моего коллеги Андрея Бурмистрова, эксперта в сфере оптимизации производительности 1С. Разработкой на платформе «1С:Предприятие 8» Андрей занимается уже более 10 лет и знает нюансы. Он расскажет, когда возникает такая проблема и рассмотрит способы решения.
Причина ошибки
Начнем с вымышленного примера, который, подчеркну, НЕ соответствует стандартам разработки в 1С. Это лишь пример. У вас есть такой код.

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

Проблема в том, что если внутри транзакции используется конструкция Попытка–Исключение, и в блоке Попытка происходит ошибка, связанная с базой данных (например, во время записи), сама транзакция не откатывается, но получает статус «только для отмены». Это означает, что в рамках этой транзакции больше нельзя выполнять никаких действий с базой: ни чтения, ни записи. Единственное возможное действие — её отмена. Формально транзакция остаётся активной, но фактически уже «нежизнеспособна».
Любая последующая попытка обратиться к базе данных из такой транзакции приведёт к сообщению «В данной транзакции уже происходили ошибки». Самое неудобное здесь то, что в тексте ошибки указывается строка кода, где происходит обращение к базе, а не та, где возникла изначальная ошибка — из-за этого найти первопричину становится значительно сложнее.
Настоящая причина появления этой ошибки — нарушение стандартов разработки 1С при обработке ошибок внутри транзакции. Иными словами, проблема кроется в логике кода, а не в платформе.
Далее разберём, как правильно реализовать подобные конструкции, но сначала нужно определить участок кода, который требует исправления.
Пример, приведённый выше, довольно простой — здесь начало транзакции, блок Попытка–Исключение и операция записи находятся в одной процедуре. На практике же всё гораздо сложнее: стек вызовов может насчитывать десятки строк, при этом транзакция открывается в одной процедуре, обработка ошибок — в другой, а сама ошибка возникает в третьей. Такая разнесённость логики значительно усложняет анализ и поиск причины сбоя.
Решение проблемы можно разделить на две части:
1) Найти проблемное место
2) Исправить код согласно стандартам 1С
Найти проблемное место можно вручную с помощью техжурнала, либо использовать Монитор. Рассмотрим оба способа.
Ищем проблемное место
Способ 1. Ручная настройка техжурнала.
Необходимо настроить технологический журнал следующим образом:
Настройка технологического журнала (logcfg.xml)
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://v8.1c.ru/v8/tech-log">
<log location="d:\Excp_Sdbl" history="48">
<event>
<eq property="name" value="EXCP"/>
<eq property="p:processName" value="Имя базы"/>
<eq property="Descr" value="В данной транзакции уже происходили ошибки!"/>
</event>
<event>
<eq property="name" value="SDBL"/>
<eq property="p:processName" value="Имя базы"/>
<eq property="Func" value="setRollbackOnly"/>
</event>
<property name="all"/>
</log>
</config>
Событие EXCP с фильтром по тексту ошибки позволяет зафиксировать все подобные случаи в журнале регистрации. Особый интерес представляет событие SDBL с фильтром Func=setRollbackOnly — по нему можно определить участок кода, где транзакции был присвоен статус «только для отмены». Если сопоставить эти события по времени и полю t:connectID, удаётся точно понять, в каком месте находится блок Попытка–Исключение, откуда была вызвана процедура, которая привела к ошибке.
Пример лога техжурнала.
49:06.002036-1,SDBL,5,process=rphost,p:processName=Demo_Lock,OSThread=28092,t:clientID=973,t:applicationName=1CV8C,t:computerName=Srv,t:connectID=4163,SessionID=7,Usr=Администратор,AppID=1CV8C,DBMS=DBMSSQL,DataBase=Srv\Demo_Lock,Trans=1,Func=setRollbackOnly,Context='Форма.Вызов : ВнешняяОбработка.Тест.Форма.Форма.Модуль.ПроцедураНаСервере
ВнешняяОбработка.Тест.Форма.Форма.Форма : 30 : Данные.Записать();'
49:06.002043-0,EXCP,6,process=rphost,p:processName=Demo_Lock,OSThread=28092,t:clientID=973,t:applicationName=1CV8C,t:computerName=Srv,t:connectID=4163,SessionID=7,Usr=Администратор,AppID=1CV8C,DBMS=DBMSSQL,DataBase=Srv\Demo_Lock,Exception=DataBaseException,Descr=В данной транзакции уже происходили ошибки!,Context='Форма.Вызов : ВнешняяОбработка.Тест.Форма.Форма.Модуль.ПроцедураНаСервере
ВнешняяОбработка.Тест.Форма.Форма.Форма : 39 : Константа1 = Константы.Константа1.Получить();'
В логах у события SDBL в свойстве Context будет указан стек вызова, который и привел к ошибке. Благодаря этому стеку можно относительно просто найти место в коде, где используется Попытка-Исключение, и переписать этот блок. Как именно его нужно переписать обсудим ниже.
Способ 2. Используем «Монитор».
Для анализа этой проблемы в «Мониторе» необходимо включить показатель «Ошибка ТЖ» и сохранить настройки.

Далее «Монитор» сам настроит техжурнал, сопоставит события, загрузит логи и присвоит каждой ошибке свою категорию. Текст ошибки отображается на соответствующей вкладке.

Но самое важное отображается на вкладке «Доп. сведения». Тут отображены события, которые связаны с ошибкой, в нашем случае это SDBL. Здесь видны все значения всех свойств события, в частности свойство Context, содержащее нужные нам сведения.

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

В таком случае при возникновении исключения при записи полное описание ошибки попадет в журнал регистрации, а при чтении константы ошибки не будет.

В данном случае причина была в делении на ноль, но из-за некорректного кода эта ошибка скрывалась за ширмой «В данной транзакции уже происходили ошибки». Используя показатель «Ошибка ТЖ» из «Монитора», можно довольно легко выявить и устранить эту проблему.
25 ноября в 12:00 на вебинаре «Скрытый налог: когда 1С висит, бизнес теряет деньги» мы расскажем, как инструмент «Монитор» для 1С помогает бизнесу сокращать финансовые потери.
Спикер: Андрей Бурмистров, 1С-эксперт по технологическим вопросам крупных внедрений
В программе:
— примеры скрытых затрат при проблемах со скоростью работы в 1С;
— разбор ключевых функций «Монитора» (долгие запросы, блокировки, взаимоблокировки, ошибки технологического журнала, уведомления о событиях);
— ответы на вопросы участников.
Все участники вебинара получат в подарок 30-дневную триал-версию «Монитора» с бесплатной установкой от наших специалистов. За 1 день и 0 рублей вы увидите проблемы производительности вашей 1С!
ВАЖНО! С 1 января 2026 года меняется лицензионная политика продукта: на каждые 3 сервера необходимо будет покупать лицензию. До конца декабря есть возможность купить лицензию без ограничения по количеству серверов.