Как узнать, на какой строке кода 1С «висит» выполнение программы или фонового задания

Программист 1С v8.3 (Управляемые формы) 1С:Комплексная автоматизация IT и автоматизация бизнеса
← На главную

Ситуация, когда длительная операция (например, закрытие месяца в 1С:Комплексная автоматизация 2 или 1С:ERP) выполняется часами, а стандартная попытка нажать кнопку «Пауза» в отладчике не приносит результата, знакома многим разработчикам. Проблема заключается в том, что если процесс «завис» на этапе выполнения тяжелого запроса к СУБД, отладчик 1С не сможет прервать выполнение до тех пор, пока сервер баз данных не вернет управление платформе. В этой статье мы подробно разберем, как «пробиться» к коду и понять, какая именно строка модуля вызывает задержку.

Почему стандартная отладка не всегда работает?

Прежде чем переходить к методам решения, проанализируем причину проблемы. Когда код 1С доходит до метода Запрос.Выполнить() или обращения к менеджеру временных таблиц, выполнение передается на сторону SQL Server. Платформа 1С в этот момент находится в режиме ожидания ответа. Кнопка Остановить (пауза) в конфигураторе посылает сигнал прерывания интерпретатору кода 1С, но он не может обработать его, пока занят ожиданием внешнего события от СУБД. Именно поэтому пауза срабатывает только «посмертно», когда запрос уже завершился.

Метод 1. Анализ через Технологический журнал (самый точный способ)

Использование Технологического журнала (ТЖ) — это наиболее профессиональный и точный метод локализации проблемы. ТЖ позволяет зафиксировать контекст выполнения кода (стек вызовов) в момент обращения к базе данных. Даже если запрос выполняется очень долго, в логах останется запись о том, какая именно процедура его инициировала.

Для настройки ТЖ создадим файл logcfg.xml в каталоге conf сервера 1С (обычно это C:\Program Files\1cv8\conf). Нам необходимо отследить событие DBMSSQL (обращение к SQL) и обязательно включить вывод свойства Context.

Рассмотрим пример настройки logcfg.xml:


<config xmlns="http://v8.1c.ru/7.4/get/logcfg">
  <log location="C:\LOGS\SQL_QUERIES" history="24">
    <event>
      <eq property="Name" value="DBMSSQL"/>
      <gt property="Duration" value="100000"/> <!-- Фиксируем запросы длительностью более 0.1 сек -->
    </event>
    <property name="All"/>
  </log>
</config>

Разберем, что мы получим в результате. После того как «зависший» запрос завершится (или вы принудительно прервете сеанс), в файле лога появится запись. Самым важным полем для нас будет Context. Оно выглядит примерно так:

Context='ОбщийМодуль.ЗакрытиеМесяцаСервер.Модуль : 1542 : Запрос.Выполнить()'

Это дает нам точный номер строки. Если запрос еще выполняется, можно периодически проверять файлы логов — современные версии платформы могут сбрасывать буфер в файл до завершения события при определенных условиях, но надежнее всего ориентироваться на завершенные или прерванные события.

Метод 2. Использование консоли администрирования кластера

В современных версиях платформы 1С v8.3 консоль администрирования предоставляет мощные средства мониторинга в реальном времени. Рассмотрим пошагово, как ими воспользоваться:

  1. Откроем консоль администрирования серверов 1С.
  2. Перейдем в раздел Сеансы нужной информационной базы.
  3. Найдем сеанс, который нагружает систему (ориентируемся по колонке Захват СУБД или Время вызова (текущее)).
  4. В свойствах сеанса или в колонке Текущий вызов СУБД можно увидеть SQL-текст запроса, который выполняется в данный момент.
  5. В последних релизах (начиная с 8.3.18+) доступна колонка Стек вызовов прямо в консоли, если на сервере включен сбор метрик. Это позволяет увидеть строку кода 1С мгновенно, не настраивая Технологический журнал.

Метод 3. Анализ на стороне SQL Server

Если штатные средства 1С не дают ответа, проанализируем ситуацию со стороны СУБД. Выясним, какой запрос выполняется и к каким таблицам он обращается. Для этого воспользуемся средой SQL Server Management Studio (SSMS).

Наиболее эффективным инструментом является процедура sp_whoisactive (ее нужно скачать и установить в базу master) или системное представление sys.dm_exec_requests.

Выполним следующий скрипт для поиска тяжелых запросов:


SELECT 
    r.session_id,
    r.status,
    r.start_time,
    r.total_elapsed_time / 1000 AS SecondsPassed,
    t.text AS QueryText,
    p.name AS DatabaseName
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
JOIN sys.databases p ON r.database_id = p.database_id
WHERE r.session_id > 50 -- Исключаем системные процессы
ORDER BY r.total_elapsed_time DESC;

Проанализируем результат. В поле QueryText мы увидим имена таблиц, например _InfoReg12345. Чтобы понять, какой объект метаданных за этим стоит, в 1С выполните следующий код (например, во внешней обработке):


ИмяТаблицы = ПолучитьСтруктуруХраненияБазыДанных().Найти("_InfoReg12345", "ИмяТаблицыХранения").Имя;
Сообщить("Это таблица объекта: " + ИмяТаблицы);

Зная, к какому регистру или документу идет обращение, мы можем воспользоваться глобальным поиском по конфигурации (Ctrl+Shift+F) и найти все места, где этот объект используется в запросах. Это значительно сузит круг поиска «зависшей» строки.

Метод 4. Самодиагностика в КА 2 и ERP

Конфигурации на базе 1С:ERP и Комплексная автоматизация 2 имеют встроенные механизмы протоколирования длительных операций. Если «висит» закрытие месяца, проанализируем следующие объекты:

Практические советы по ускорению поиска

Если вы обнаружили, что запрос висит, обратите внимание на Wait Stats (статистику ожиданий) в SQL Server. Если тип ожидания LCK_M_..., это означает, что ваш код не «медленный», а просто заблокирован другим процессом. В этом случае отладка конкретной строки не поможет — нужно искать «виновника» блокировки в той же консоли администрирования 1С или через отчеты SSMS по блокировкам.

Также полезно использовать Монитор ресурсов. Если процесс sqlservr.exe активно читает диск, скорее всего, запросу не хватает индексов или происходит сканирование огромных временных таблиц. Проверьте, не раздута ли база tempdb — это часто происходит при неоптимальных соединениях в сложных расчетах закрытия месяца.

Резюме

Для того чтобы вычислить «зависшую» строку кода, когда обычный отладчик бессилен, используйте следующую стратегию:

  1. Проверьте Консоль администрирования 1С — это самый быстрый способ увидеть текущий контекст в новых версиях платформы.
  2. Настройте Технологический журнал с событием DBMSSQL и свойством Context — это даст 100% результат после завершения или прерывания процесса.
  3. Используйте SQL-запросы к системным представлениям СУБД, чтобы понять, какой текст запроса выполняется «под капотом» и к каким таблицам он обращается.

Такой комплексный подход позволит вам не ждать часами окончания операции, а оперативно локализовать узкое место в коде 1С.

← На главную