Прерывание долгого запроса в 1С: клиент, кластер, СУБД
Содержание
Клавиша Ctrl+Break останавливает любой зависший запрос — так думают, и в клиент-серверной базе ошибаются. Запрос уходит на сервер 1С, оттуда в СУБД, и клавиатура клиента на него уже не влияет. Прерывать приходится на том уровне, где запрос реально выполняется.
Поэтому первый шаг — понять, где именно всё встало: в коде на клиенте, в сеансе рабочего процесса на сервере приложений или уже внутри СУБД на блокировке. От этого зависит, какой инструмент вас спасёт — горячая клавиша, консоль кластера или KILL процесса в базе данных. Ниже — по каждому уровню.
1cv8.exe. Клиент-серверная — завершить сеанс в консоли кластера, транзакция откатится.KILL в SQL Server, pg_terminate_backend в PostgreSQL..dt). Прерывать её на полпути опасно — дождитесь завершения или восстановите из копии.Когда помогает Ctrl+Break, а когда нет
Ctrl+Break прерывает выполнение встроенного языка на той стороне, где оно идёт в данный момент. Это работает для:
- зависшего цикла в обработке, которая считает на клиенте;
- выполнения кода в отладчике Конфигуратора;
- долгого формирования на тонком клиенте, пока управление ещё в клиентской процедуре.
А вот чего Ctrl+Break не сделает: он не прервёт запрос, который уже передан на сервер 1С и выполняется в СУБД. Пока сервер ждёт ответ от базы данных, клиентская сессия просто висит в ожидании, и нажатие клавиш уходит в пустоту.
В клиент-серверной базе Ctrl+Break часто «не срабатывает» именно по этой причине. Проблема не в клавише — запрос физически исполняется не там, где вы жмёте.
В Конфигураторе отладку останавливают через Shift+F5 (команда «Остановить») или кнопку остановки на панели отладки. Это завершит отлаживаемый сеанс целиком, со всеми незавершёнными транзакциями.
Прерывание из консоли запросов и внешних обработок
Долгие запросы чаще всего гоняют через внешние обработки — консоли запросов, инструменты разработчика. Если такой запрос завис, у вас два пути.
Закрыть окно обработки. Иногда достаточно закрыть форму консоли — платформа пошлёт серверу сигнал на отмену. Но если запрос уже глубоко в СУБД, окно тоже «зависнет» на закрытии.
Завершить сеанс, в котором работает обработка. Это надёжнее. Внешняя обработка выполняется в вашем же сеансе, поэтому прерывание сводится к завершению сеанса (см. следующий раздел) или снятию процесса в файловом варианте.
Перед запуском тяжёлого запроса в консоли полезно заранее знать номер своего сеанса — так вы быстро найдёте его в списке, если придётся прерывать. Номер виден в заголовке окна или через функцию НомерСеансаИнформационнойБазы().
Отдельная ситуация — встроенный отладчик встроенного языка. Если запрос вызван из кода и вы хотите его разобрать, а не просто убить, ставьте точку останова до строки с Запрос.Выполнить() и смотрите текст запроса и параметры. Готовый текст удобно скопировать в консоль и прогнать на небольшой выборке, ограничив период или добавив ПЕРВЫЕ 100.
Завершение сеанса в консоли администрирования кластера
Для клиент-серверной базы это основной инструмент. Зависший сеанс завершается принудительно, и сервер откатывает его транзакцию.
Через оснастку «Администрирование серверов 1С Предприятия» (Windows):
- Разверните
Центральные серверы → ваш сервер → Кластеры → ваш кластер → Сеансы. - Найдите нужный сеанс — по имени пользователя, по приложению (толстый клиент, фоновое задание, веб-клиент) или по времени начала.
- Правой кнопкой —
Удалить. Сеанс помечается на завершение, рабочий процесс откатывает транзакцию и закрывает соединение.
Через утилиту командной строки 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С ждёт ответ от стороннего сервиса, сеанс тоже «висит», но причина не в СУБД, а в сети. Такой сеанс снимается так же, через консоль кластера, но лечится настройкой таймаутов на стороне интеграции, а не оптимизацией запроса.
Частые вопросы
Почему Ctrl+Break не останавливает мой запрос?
Что произойдёт с данными, если завершить зависший сеанс?
Как понять, завис запрос или просто долго считает?
wait_time и блокирующий процесс. Если процесс стоит на блокировке и wait_time растёт, он ждёт, а не работает. Если же активно грузит процессор, возможно, это тяжёлый, но живой запрос — дайте ему закончить.Можно ли прервать запрос в файловой базе?
1cv8.exe в «Диспетчере задач», но после этого нужно прогнать тестирование и исправление базы, потому что файлы закрылись некорректно.Чем pg_cancel_backend отличается от pg_terminate_backend?
pg_cancel_backend отменяет текущий запрос, оставляя соединение живым, — это мягкий вариант. pg_terminate_backend разрывает само соединение целиком. Сначала пробуйте отмену, к завершению переходите, если запрос не отменяется.