Прерывание долгого запроса в 1С: клиент, кластер, СУБД

· 9 мин

Содержание

Клавиша Ctrl+Break останавливает любой зависший запрос — так думают, и в клиент-серверной базе ошибаются. Запрос уходит на сервер 1С, оттуда в СУБД, и клавиатура клиента на него уже не влияет. Прерывать приходится на том уровне, где запрос реально выполняется.

Поэтому первый шаг — понять, где именно всё встало: в коде на клиенте, в сеансе рабочего процесса на сервере приложений или уже внутри СУБД на блокировке. От этого зависит, какой инструмент вас спасёт — горячая клавиша, консоль кластера или KILL процесса в базе данных. Ниже — по каждому уровню.

Где зависает выполнение?

Когда помогает Ctrl+Break, а когда нет

Ctrl+Break прерывает выполнение встроенного языка на той стороне, где оно идёт в данный момент. Это работает для:

  • зависшего цикла в обработке, которая считает на клиенте;
  • выполнения кода в отладчике Конфигуратора;
  • долгого формирования на тонком клиенте, пока управление ещё в клиентской процедуре.

А вот чего Ctrl+Break не сделает: он не прервёт запрос, который уже передан на сервер 1С и выполняется в СУБД. Пока сервер ждёт ответ от базы данных, клиентская сессия просто висит в ожидании, и нажатие клавиш уходит в пустоту.

В клиент-серверной базе Ctrl+Break часто «не срабатывает» именно по этой причине. Проблема не в клавише — запрос физически исполняется не там, где вы жмёте.

В Конфигураторе отладку останавливают через Shift+F5 (команда «Остановить») или кнопку остановки на панели отладки. Это завершит отлаживаемый сеанс целиком, со всеми незавершёнными транзакциями.

Прерывание из консоли запросов и внешних обработок

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

Закрыть окно обработки. Иногда достаточно закрыть форму консоли — платформа пошлёт серверу сигнал на отмену. Но если запрос уже глубоко в СУБД, окно тоже «зависнет» на закрытии.

Завершить сеанс, в котором работает обработка. Это надёжнее. Внешняя обработка выполняется в вашем же сеансе, поэтому прерывание сводится к завершению сеанса (см. следующий раздел) или снятию процесса в файловом варианте.

Перед запуском тяжёлого запроса в консоли полезно заранее знать номер своего сеанса — так вы быстро найдёте его в списке, если придётся прерывать. Номер виден в заголовке окна или через функцию НомерСеансаИнформационнойБазы().

Отдельная ситуация — встроенный отладчик встроенного языка. Если запрос вызван из кода и вы хотите его разобрать, а не просто убить, ставьте точку останова до строки с Запрос.Выполнить() и смотрите текст запроса и параметры. Готовый текст удобно скопировать в консоль и прогнать на небольшой выборке, ограничив период или добавив ПЕРВЫЕ 100.

Завершение сеанса в консоли администрирования кластера

Для клиент-серверной базы это основной инструмент. Зависший сеанс завершается принудительно, и сервер откатывает его транзакцию.

Через оснастку «Администрирование серверов 1С Предприятия» (Windows):

  1. Разверните Центральные серверы → ваш сервер → Кластеры → ваш кластер → Сеансы.
  2. Найдите нужный сеанс — по имени пользователя, по приложению (толстый клиент, фоновое задание, веб-клиент) или по времени начала.
  3. Правой кнопкой — Удалить. Сеанс помечается на завершение, рабочий процесс откатывает транзакцию и закрывает соединение.

Через утилиту командной строки rac (Linux и Windows):

rac session list --cluster=<uuid-кластера>
rac session terminate --cluster=<uuid-кластера> --session=<uuid-сеанса>

Сначала session list покажет сеансы с их идентификаторами, затем session terminate снимет нужный. Идентификатор кластера даёт команда rac cluster list. Полный список параметров — в rac help session; не угадывайте ключи, которых нет в справке.

Завершение сеанса откатывает незавершённую транзакцию и обрывает работу пользователя — несохранённые данные он потеряет. Снимайте чужой сеанс только когда убедились, что он действительно завис, а не просто выполняет долгую штатную операцию.

В файловой базе кластера нет и этого списка тоже. Там единственный способ — закрыть приложение, а если не закрывается, снять процесс 1cv8.exe через «Диспетчер задач». Это грубо: платформа не успеет корректно закрыть файлы, поэтому после такого снятия обязательно проверьте базу через Конфигуратор → Администрирование → Тестирование и исправление.

Снятие зависшего процесса в СУБД

Если сеанс 1С висит, а в консоли кластера видно, что он давно в одной операции, — запрос стоит в базе данных. Чаще всего на блокировке: один процесс ждёт, пока другой освободит таблицу.

SQL Server. Найдите заблокированный и блокирующий процессы и снимите нужный по его идентификатору (SPID):

-- кто кого блокирует
SELECT session_id, blocking_session_id, wait_type, wait_time
FROM sys.dm_exec_requests
WHERE blocking_session_id <> 0;

-- снять процесс
KILL 57;

KILL откатывает транзакцию процесса. Откат большой транзакции может сам идти минуты — это нормально, дождитесь.

PostgreSQL. Смотрите активность и снимайте процесс по его PID. Сначала мягко — отмена запроса без разрыва соединения, и только если не помогло — жёстко:

-- активные запросы
SELECT pid, state, wait_event, query
FROM pg_stat_activity
WHERE state <> 'idle';

-- мягкая отмена запроса
SELECT pg_cancel_backend(12345);

-- принудительное завершение соединения
SELECT pg_terminate_backend(12345);

KILL и pg_terminate_backend обрывают сеанс 1С вместе с его транзакцией. Это крайняя мера: применяйте, когда через консоль кластера сеанс снять не удаётся, и понимаете, какой именно процесс снимаете. Снятие «не того» SPID уронит работающего пользователя.

Сопоставить процесс СУБД с конкретным сеансом 1С помогает технологический журнал: события DBMSSQL (для SQL Server) и DBPOSTGRS (для PostgreSQL) содержат текст запроса и длительность, а по контексту события видно, какой сеанс и какой вызов встроенного языка его породил. В острой ситуации обычно хватает и более простой связки «сеанс в консоли кластера давно в одной операции → в СУБД растёт wait_time → вот блокирующий процесс».

Если блокировок много и они цепляются друг за друга, снимайте не любой процесс, а самый «корневой» — тот, у которого blocking_session_id равен нулю, то есть он сам никого не ждёт, а его ждут остальные. Снятие корневого часто распускает всю очередь разом.

Когда запрос лучше не трогать

Не каждая долгая операция — зависание. Перед тем как кого-то снимать, стоит убедиться, что процесс действительно мёртв, а не просто занят.

  • 🟢 Штатная тяжёлая обработка. Закрытие месяца , перепроведение документов за период, групповое формирование — это минуты и десятки минут честной работы. Снимете на середине — откат займёт столько же, и начинать придётся заново.
  • 🟢 Загрузка данных и обмены. Пакетная загрузка, синхронизация, первичное заполнение регистров тоже выглядят как «висит», но прогресс идёт. Смотрите на нагрузку процессора и дискового ввода-вывода: если они живые, процесс работает.
  • 🔴 Монопольные операции Конфигуратора. Обновление конфигурации базы данных, загрузка .dt, тестирование и исправление — их нельзя обрывать на полпути снятием процесса: структуру можно оставить в несогласованном состоянии. Если такая операция «зависла», не снимайте её, а восстановите базу из резервной копии и повторите.

Правило простое: сначала смотрим, есть ли признаки жизни (растёт ли счётчик обработанных, грузится ли процессор, движется ли wait_time у ждущего и работает ли блокирующий). Прерываем только то, что стоит мёртвым грузом и мешает остальным.

Остановка фоновых и регламентных заданий

Отдельная причина «вечного» запроса — фоновое задание, которое запустилось по расписанию и застряло. Пользователь его не видит, но нагрузку оно создаёт.

В режиме «1С:Предприятие» заданиями управляют из раздела обслуживания. В «1С:Бухгалтерии 3.0» это Администрирование → Обслуживание → Регламентные и фоновые задания. Там видно, какое задание выполняется, сколько длится, и можно:

  • открыть регламентное задание и отключить расписание, чтобы оно не стартовало снова;
  • на вкладке фоновых заданий найти активное и принудительно завершить его.

В консоли кластера такое задание видно как отдельный сеанс с типом приложения «Фоновое задание» (BackgroundJob). Снять его можно так же, как обычный сеанс — командой session terminate или через оснастку.

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

На время разбора массовых проблем удобно временно отключить автозапуск регламентных заданий целиком (в клиент-серверном варианте — параметр блокировки регламентных заданий в свойствах базы в консоли кластера). Не забудьте вернуть обратно.

Как сделать, чтобы запросы не зависали

Прерывание — лечение симптома. Чтобы запрос не приходилось останавливать, работают на причинах. Вот что реально сокращает число зависаний.

  • 🧱 Запросы в цикле. Классическая беда: запрос внутри обхода коллекции. Соберите данные одним пакетным запросом, а в цикле обрабатывайте выборку.
  • 🧊 Виртуальные таблицы. Условия для ОстаткиИОбороты, Остатки и т.п. задавайте в параметрах виртуальной таблицы, а не в секции ГДЕ после соединения — иначе платформа сначала поднимет всё, потом отфильтрует.
  • 🗂 Временные таблицы и индексы. Промежуточные наборы кладите во временные таблицы и индексируйте поля соединения — это снимает нагрузку с СУБД.
  • 🔒 Управляемые блокировки. Короткие транзакции и точечные блокировки вместо долгих — меньше шансов, что два процесса встанут в очередь друг к другу.
  • ⏱ Таймаут ожидания блокировки. В клиент-серверной базе разумно ограничить время ожидания на управляемой блокировке: тогда процесс, который не дождался ресурса, завершится с понятной ошибкой сам, а не повиснет в очереди навсегда.
  • 📊 Замер и план. Долгие запросы ищут не на глаз: технологический журнал, анализ плана запроса в СУБД, показатель производительности APDEX. Сначала находите самый тяжёлый запрос, потом оптимизируете его, а не всё подряд.

Отдельно стоит следить за соединениями с внешними источниками данных и веб-сервисами внутри запросов и обработок: если 1С ждёт ответ от стороннего сервиса, сеанс тоже «висит», но причина не в СУБД, а в сети. Такой сеанс снимается так же, через консоль кластера, но лечится настройкой таймаутов на стороне интеграции, а не оптимизацией запроса.

Перед запуском тяжёлого запроса в рабочей базе
Выполнено: 0 / 5

Частые вопросы

Почему Ctrl+Break не останавливает мой запрос?
Потому что запрос уже выполняется на сервере 1С или в СУБД, а не в клиенте. Горячая клавиша прерывает только код, исполняемый на той стороне, где вы его нажимаете. Прерывайте через консоль кластера или снятием процесса в базе данных.
Что произойдёт с данными, если завершить зависший сеанс?
Сервер откатит незавершённую транзакцию — база останется целой, но всё, что пользователь не успел записать, пропадёт. Проведённые и записанные ранее документы не пострадают.
Как понять, завис запрос или просто долго считает?
Посмотрите в консоли кластера время и состояние сеанса, а в СУБД — wait_time и блокирующий процесс. Если процесс стоит на блокировке и wait_time растёт, он ждёт, а не работает. Если же активно грузит процессор, возможно, это тяжёлый, но живой запрос — дайте ему закончить.
Можно ли прервать запрос в файловой базе?
Корректно — только закрыв приложение. Если не закрывается, снимают процесс 1cv8.exe в «Диспетчере задач», но после этого нужно прогнать тестирование и исправление базы, потому что файлы закрылись некорректно.
Чем pg_cancel_backend отличается от pg_terminate_backend?
pg_cancel_backend отменяет текущий запрос, оставляя соединение живым, — это мягкий вариант. pg_terminate_backend разрывает само соединение целиком. Сначала пробуйте отмену, к завершению переходите, если запрос не отменяется.