Каждый разработчик 1С рано или поздно сталкивается с критической ситуацией: на рабочей («живой») базе данных у пользователя возникает ошибка при проведении документа. Клиенты стоят в очереди, руководство требует немедленного исправления, а восстанавливать резервную копию базы данных слишком долго. Естественное желание программиста — запустить отладчик, поставить точку останова в процедуре проведения и посмотреть, что происходит с переменными и запросами.
Однако классическая отладка внутри транзакции проведения на «проде» — это огромный риск. Как только выполнение кода останавливается на точке останова, СУБД блокирует таблицы базы данных для всех остальных пользователей. В результате работа всей компании мгновенно парализуется, а другие сеансы начинают аварийно завершаться по таймауту ожидания блокировки. Выясним причину этой проблемы и подробно разберем эффективные профессиональные методы, которые позволяют безопасно локализовать и устранить ошибку прямо на рабочей базе без блокирования пользователей.
Один из самых простых и быстрых способов заглянуть «внутрь» выполняющегося кода без удержания транзакции — это стандартный инструмент платформы Замер производительности. Этот подход позволяет зафиксировать весь путь выполнения алгоритма за доли секунды.
Рассмотрим по шагам, как правильно выполнить эту процедуру:
Перед нами открывается подробная таблица со списком всех выполненных строк кода, функций и запросов. Мы можем детально проанализировать, в какие условия заходил алгоритм, какие функции вызывались и сколько времени заняло выполнение каждой строки. Поскольку физической остановки транзакции не происходило, пользователи базы данных даже не заметят нашей работы.
Если для анализа ситуации обязательно нужно пройтись по коду пошагово с вычислением выражений в табло, лучшим решением станет использование механизма Database Snapshots на уровне СУБД (например, MS SQL Server). Это современная альтернатива классическому долгому восстановлению бэкапа.
Проанализируем преимущества этого подхода:
Когда нам нужно увидеть значения конкретных переменных, таблиц значений или результатов запросов в момент проведения, мы можем применить так называемую «printf-отладку». Чтобы не вносить изменения в основную конфигурацию, задействуем механизм расширений.
Создадим временное расширение и перехватим интересующий нас метод проведения с помощью аннотации &Вместо. Вместо остановки кода запишем все необходимые данные во внешний источник. Посмотрим на пример кода, который записывает промежуточные таблицы в текстовый файл на сервере:
&Вместо("ОбработкаПроведения")
Процедура Расш_ОбработкаПроведения(Отказ, РежимПроведения)
// Вызываем оригинальный алгоритм проведения
ПродолжитьВызов(Отказ, РежимПроведения);
// Записываем отладочную информацию без остановки потока
ТекстЛога = Новый ТекстовыйДокумент;
ТекстЛога.ДобавитьСтроку("--- Старт логирования проведения ---");
ТекстЛога.ДобавитьСтроку("Отказ: " + Строка(Отказ));
// Пример логирования таблицы движений
Для Каждого СтрокаДвижения Из ЭтотОбъект.Движения.Хозрасчетный Цикл
ТекстЛога.ДобавитьСтроку(Шаблон("Счет: %1, Сумма: %2", СтрокаДвижения.СчетДт, СтрокаДвижения.Сумма));
КонецЦикла;
Попытка
ТекстЛога.Записать("C:\temp\debug_post.txt", КодировкаТекста.UTF8);
Исключение
ЗаписьЖурналаРегистрации("ОтладкаПроведения", УровеньЖурналаРегистрации.Ошибка,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецПроцедуры
Такой подход позволяет моментально получить снимок состояния данных в процессе проведения. Логировать информацию можно также в стандартный Журнал регистрации с помощью метода ЗаписьЖурналаРегистрации или в специально созданный временный регистр сведений.
Если проблему нужно исследовать в динамике, но строго без фиксации изменений в базе данных, мы можем написать небольшую внешнюю обработку. Мы программно запустим транзакцию, выполним все этапы заполнения и проведения объекта, установим точки останова в нужных местах алгоритма, а в самом конце принудительно отменим транзакцию.
Рассмотрим пример реализации такого безопасного алгоритма:
Процедура ВыполнитьБезопаснуюОтладкуНаСервере(СсылкаНаДокумент)
ОбъектДокумент = СсылкаНаДокумент.ПолучитьОбъект();
НачатьТранзакцию();
Попытка
// Эмулируем ручное проведение документа
ОбъектДокумент.Записать(РежимЗаписиДокумента.Проведение);
// Сюда можно поставить точку останова.
// Данные подготовлены и рассчитаны, но еще не зафиксированы в СУБД.
ВыборкаДанных = ОбъектДокумент.Движения.Хозрасчетный.Выгрузить();
// Принудительно вызываем исключение, чтобы гарантировать откат
ВызватьИсключение "Откат отладочной транзакции";
Исключение
// Любые изменения, сделанные в процессе отладки, бесследно удаляются
ОтменитьТранзакцию();
КонецПопытки;
КонецПроцедуры
Важный нюанс: хотя этот метод гарантирует, что тестовые данные не запишутся в рабочую базу, во время остановки на точке останова внутри конструкции НачатьТранзакцию() блокировки СУБД все равно будут наложены на изменяемые таблицы. Поэтому использовать этот способ на рабочей базе следует крайне осторожно и только в периоды минимальной активности пользователей.
Некоторые разработчики ошибочно полагают, что Технологический журнал полезен только администраторам СУБД для поиска утечек памяти или взаимоблокировок. На самом деле, при правильной настройке файла logcfg.xml, ТЖ превращается в мощнейший инструмент бесконтактной отладки.
Мы можем настроить сбор событий СУБД (например, DBMSSQL или SDBL) с жестким фильтром по конкретному имени пользователя или идентификатору его сеанса (SessionID). В логах технологического журнала мы увидим:
Анализируя эти данные, можно с легкостью понять логику работы алгоритма и найти логическую ошибку в запросах без непосредственного подключения интерактивного отладчика к процессу.
Это превентивный архитектурный метод, который избавляет разработчиков от необходимости отладки транзакций на «проде». Современный стандарт разработки в среде 1С требует разделения бизнес-логики и работы с базой данных.
Разберем по шагам правильное проектирование алгоритма проведения:
В современных конфигурациях 1С (особенно построенных на базе БСП) проведение документов часто выполняется асинхронно — в фоновых заданиях. Отлаживать фоновые задания на рабочей базе крайне неудобно.
Для решения этой проблемы мы можем использовать параметр запуска клиента /C РежимОтладки. Этот параметр сообщает механизмам БСП, что все фоновые задания должны выполняться синхронно, непосредственно в сеансе текущего пользователя. Это позволяет локализовать выполнение кода внутри одного конкретного клиентского соединения, упрощая изоляцию и минимизируя влияние отладочного процесса на другие фоновые процессы системы.