Запрос в консоли 1С выполняется бесконечно: как прервать его и не уронить базу

· 9 мин

Содержание

Остановить зависшую консоль запросов 1С проще всего так: в клиент-серверной базе откройте консоль администрирования кластера, найдите свой сеанс в списке сеансов базы и прервите его текущий серверный вызов или удалите сеанс. В файловой базе остаётся завершить процесс 1cv8c.exe (или 1cv8.exe) в Диспетчере задач. Комбинация Ctrl+Break помогает, только если код крутится на клиенте, а не ждёт ответа от сервера.

Выбор способа зависит от того, где именно «висит» запрос: в клиенте, в рабочем процессе сервера 1С или в самой СУБД. Чем ниже уровень, тем жёстче вмешательство и тем выше шанс задеть чужие сеансы. Поэтому идите сверху вниз и переходите к следующему способу, только если предыдущий не сработал.

Сравнение способов остановить запрос

СпособКогда подходитЧто затронет
Ctrl+Break в окне 1СКод консоли выполняется на клиенте (обход результата, вывод в табличный документ)Только ваш сеанс
Прервать серверный вызов в консоли кластераЗапрос выполняется на сервере 1С, сеанс живТолько текущий вызов, сеанс остаётся
Удалить сеанс в консоли кластера или через racПрерывание вызова не помоглоВаш сеанс целиком, несохранённые данные теряются
Снять процесс 1cv8c.exe / 1cv8.exeФайловая база или клиент перестал отвечатьВсе окна этого клиента
Отмена запроса в СУБДСервер 1С не может прервать ожидание СУБДОдно соединение с СУБД
Завершить rphost.exeКрайний случай, всё остальное не помоглоВсе сеансы на этом рабочем процессе

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

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

🔎 Что проверить за пару минут:

  1. Откройте Диспетчер задач на своём компьютере. Если 1cv8c.exe грузит процессор на 100% одного ядра, работает клиентский код: например, консоль выводит миллион строк в табличный документ.
  2. Если клиент почти не нагружен, работа идёт на сервере. На сервере 1С посмотрите загрузку процессов rphost.exe.
  3. В консоли кластера откройте список сеансов базы и найдите свой сеанс. Добавьте в список колонки с текущим временем вызова и временем вызова СУБД (настраиваются через выбор колонок списка). Если оба значения растут, запрос выполняется в СУБД.
  4. Если время вызова растёт, а время в СУБД стоит на месте, сеанс может ждать блокировку, которую держит другой пользователь. Тогда виноват не ваш запрос, а чужая транзакция.

💡 Если за последние минуты значения в колонках не меняются, а процессор свободен, клиент мог потерять связь с сервером. В этом случае помогает только закрыть окно клиента.

Типичные причины «вечного» запроса

  • 🐢 Запрос к большому регистру без отбора: например, обороты за пять лет по всем субконто.
  • 🔗 Соединение таблиц без условия, которое превращается в декартово произведение на миллионы строк.
  • 📥 Вывод огромного результата в табличный документ консоли: сам запрос уже отработал, а клиент рисует строки.
  • 🔒 Ожидание блокировки от документа, который в этот момент проводит другой пользователь.
  • 🧮 Отбор по полю виртуальной таблицы в ГДЕ вместо параметров виртуальной таблицы.

Прерывание запроса в консоли кластера серверов 1С

Для клиент-серверной базы это основной и самый аккуратный способ. Нужна оснастка «Администрирование серверов 1С:Предприятия» и права администратора кластера.

Пошагово

  1. Запустите консоль администрирования серверов 1С на сервере или на рабочей станции, где установлены компоненты администрирования.
  2. Раскройте Центральные серверы 1С:Предприятия → <имя сервера> → Кластеры → <кластер> → Информационные базы → <ваша база> → Сеансы.
  3. Найдите сеанс по имени пользователя, компьютеру и приложению. У консоли запросов приложение обычно «Тонкий клиент» или «Толстый клиент».
  4. Кликните по сеансу правой кнопкой. В актуальных версиях платформы есть команда прерывания текущего серверного вызова: она снимает только выполняемый запрос, а сам сеанс остаётся открытым.
  5. Если команды нет или вызов не прерывается, выберите Удалить. Сеанс будет завершён, у пользователя появится сообщение о разрыве соединения.

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

💡 Чтобы не искать сеанс среди сотни похожих, запускайте консоль запросов под отдельным пользователем, например «Администратор_Запросы». Тогда в списке сеансов его видно сразу.

Если консоль кластера не открывается

Если оснастка выдаёт ошибку при запуске, чаще всего не зарегистрирована библиотека radmin.dll нужной версии платформы. Её регистрируют от имени администратора командой regsvr32 с полным путём к файлу в каталоге bin установленной платформы:

regsvr32 "C:\Program Files\1cv8\8.3.25.1286\bin\radmin.dll"

Номер версии в пути подставьте свой: он должен совпадать с версией сервера 1С.

Остановка сеанса из командной строки через rac

Когда графической консоли под рукой нет, тот же результат даёт утилита rac. Она работает через сервер администрирования ras, который должен быть запущен (по умолчанию порт 1545).

Последовательность команд такая:

rem 1. Узнать идентификатор кластера
rac cluster list

rem 2. Список баз кластера с их идентификаторами
rac infobase summary list --cluster=<id кластера>

rem 3. Сеансы конкретной базы
rac session list --cluster=<id кластера> --infobase=<id базы>

rem 4. Завершить нужный сеанс
rac session terminate --cluster=<id кластера> --session=<id сеанса>

Если на кластере заданы администраторы, к командам добавляют --cluster-user и --cluster-pwd. В выводе rac session list ищите строку с вашим именем пользователя в поле user-name и компьютером в host.

Прерывание только серверного вызова, без завершения сеанса, в новых версиях платформы тоже доступно из rac. Точный синтаксис для своей версии смотрите в справке rac help session.

Завершение процесса 1С через Диспетчер задач

Файловая база

У файловой базы нет сервера, где можно найти сеанс. Запрос выполняется внутри самого клиента, поэтому остановить его можно только вместе с клиентом.

  1. Нажмите Ctrl+Shift+Esc, откройте вкладку «Подробности».
  2. Найдите 1cv8c.exe (тонкий клиент) или 1cv8.exe (толстый клиент). Если открыто несколько баз, ориентируйтесь по загрузке процессора: зависшая консоль обычно занимает целое ядро.
  3. Нажмите «Снять задачу».

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

Клиент-серверная база

Снятие 1cv8c.exe на рабочей станции в клиент-серверном режиме закрывает окно, но не всегда сразу останавливает запрос. Рабочий процесс сервера может ещё какое-то время дорабатывать вызов, пока не обнаружит разрыв соединения. Поэтому после снятия клиента проверьте в консоли кластера, что сеанс исчез, и при необходимости удалите его вручную.

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

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

Бывает, что сервер 1С отправил запрос в СУБД и ждёт ответа, а прерывание сеанса не срабатывает сразу. Тогда запрос снимают в самой СУБД. Делает это администратор баз данных с соответствующими правами.

Microsoft SQL Server

Найдите активные запросы, отсортированные по длительности:

SELECT r.session_id, r.status, r.wait_type, r.total_elapsed_time / 1000 AS sec,
       s.host_name, s.program_name, t.text
FROM sys.dm_exec_requests r
JOIN sys.dm_exec_sessions s ON s.session_id = r.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE s.is_user_process = 1
ORDER BY r.total_elapsed_time DESC;

Запросы от 1С приходят с сервера 1С, поэтому host_name будет именем сервера приложений, а не компьютера пользователя. Узнать свой запрос помогает текст: имена таблиц вида _AccumRg…, _Document… и время начала, совпадающее с запуском консоли. Затем:

KILL 57;  -- номер session_id из результата выше

PostgreSQL

SELECT pid, now() - query_start AS duration, state, left(query, 200)
FROM pg_stat_activity
WHERE state <> 'idle'
ORDER BY duration DESC;

SELECT pg_cancel_backend(12345);     -- мягко: отменить запрос
-- SELECT pg_terminate_backend(12345); -- жёстко: закрыть соединение

Начинайте с pg_cancel_backend: он отменяет только запрос. pg_terminate_backend рвёт соединение целиком.

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

Как сделать консоль запросов прерываемой из кода

Если вы дорабатываете свою консоль или пишете обработки с тяжёлыми запросами, заложите возможность остановки заранее.

Проверка Ctrl+Break в цикле

Сам Запрос.Выполнить() прервать нажатием клавиш нельзя: платформа ждёт ответа от СУБД. А вот обход результата можно сделать прерываемым. Метод ОбработкаПрерыванияПользователя() проверяет, нажал ли пользователь Ctrl+Break, и останавливает выполнение кода на клиенте:

Выборка = Запрос.Выполнить().Выбрать();
Счетчик = 0;
Пока Выборка.Следующий() Цикл
    Счетчик = Счетчик + 1;
    Если Счетчик % 1000 = 0 Тогда
        ОбработкаПрерыванияПользователя();
    КонецЕсли;
    // обработка строки выборки
КонецЦикла;

Проверка раз в 1000 строк почти не замедляет цикл. Учтите, что метод действует в коде, который выполняется на клиенте. Цикл в серверной процедуре так не остановить.

Выполнение запроса в фоновом задании

Надёжнее вынести тяжёлый запрос в фоновое задание. Тогда форма консоли не блокируется, а задание можно отменить кнопкой:

// В модуле формы, на сервере
&НаСервереБезКонтекста
Функция ЗапуститьЗапрос(ТекстЗапроса)
    Параметры = Новый Массив;
    Параметры.Добавить(ТекстЗапроса);
    Задание = ФоновыеЗадания.Выполнить("МойОбщийМодуль.ВыполнитьЗапрос", Параметры);
    Возврат Задание.УникальныйИдентификатор;
КонецФункции

&НаСервереБезКонтекста
Процедура ОтменитьЗапрос(Идентификатор)
    Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(Идентификатор);
    Если Задание <> Неопределено Тогда
        Задание.Отменить();
    КонецЕсли;
КонецПроцедуры

Процедура ВыполнитьЗапрос должна лежать в общем серверном модуле и сама сохранять результат, например во временное хранилище. Фоновые задания видны и в консоли кластера как отдельные сеансы, так что их тоже можно снять оттуда.

Ограничение потребления ресурсов на кластере

В актуальных версиях платформы в свойствах кластера есть механизм ограничений потребления ресурсов. Администратор задаёт, например, предельную длительность серверного вызова или объём чтения из СУБД, и выбирает действие при превышении: предупредить или прервать текущий серверный вызов. Это страхует от того, что чей-то запрос из консоли будет «висеть» часами.

Профилактика: как писать запросы, которые не вешают базу

Лучший способ остановки — не запускать запрос, который нельзя дождаться.

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

Несколько правил подробнее:

  • 📏 Пробный прогон с ПЕРВЫЕ. Запрос ВЫБРАТЬ ПЕРВЫЕ 100 покажет, правильны ли поля и соединения, за секунды. Убирайте ограничение, когда уверены в результате.
  • 📅 Параметры виртуальных таблиц. Отбор РегистрНакопления.Продажи.Обороты(&Начало, &Конец, , Номенклатура = &Товар) фильтрует данные до расчёта оборотов. Тот же отбор в ГДЕ заставит СУБД сначала посчитать всё.
  • 🧩 Временные таблицы вместо вложенных запросов. Соединение с вложенным запросом часто получает плохой план. Временная таблица с индексом по полю связи работает предсказуемее.
  • 🖨️ Не выводите миллион строк. Если нужен итог, группируйте в запросе. Табличный документ на сотни тысяч строк зависнет даже при быстром запросе.
  • 🕐 Время запуска. Тяжёлую выборку по рабочей базе в момент закрытия месяца или массового проведения легко поймать на блокировках. Аналитику гоняйте на копии.

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

Можно ли прервать запрос, не закрывая консоль?
Да, в клиент-серверной базе: прервите текущий серверный вызов сеанса в консоли кластера. Консоль получит ошибку выполнения, но окно останется открытым.
Почему Ctrl+Break не останавливает выполнение запроса?
Пока запрос выполняется в СУБД, клиент ждёт ответа сервера и не обрабатывает прерывание. Сочетание срабатывает только на клиентском коде, например при выводе результата.
Останутся ли изменения в базе после принудительной остановки?
Если запрос только читал данные, менять нечего. Если в коде консоли была запись внутри транзакции, незавершённая транзакция откатится.
Сколько ждать после удаления сеанса?
Обычно сеанс исчезает за несколько секунд. Если в СУБД идёт долгий запрос, рабочий процесс может дорабатывать его дольше; тогда снимите запрос на стороне СУБД.
Мешает ли зависший запрос другим пользователям?
Да, если он нагружает сервер СУБД или держит блокировки. Длинное чтение большого регистра тормозит проведение у всех, кто работает с этим регистром.