Каждый системный администратор и специалист 1С сталкивался с ситуацией: пользователь формирует тяжелый отчет с периодом за несколько лет, сеанс намертво зависает, блокирует таблицы и тормозит работу остальных коллег. При попытке принудительно удалить такой сеанс через стандартную консоль администрирования кластера ничего не происходит — список обновляется, а сеанс с прежним номером продолжает оставаться активным. Перезапускать службу сервера целиком не вариант, ведь это приведет к обрыву работы всех остальных пользователей предприятия.
Разберем детально, почему так происходит и какие существуют практические способы «мягко» и точечно завершить зависший сеанс.
Проанализируем архитектуру взаимодействия платформы 1С и СУБД в момент выполнения тяжелых операций. Когда пользователь запускает построение объемного отчета, рабочий процесс сервера 1С (rphost) генерирует сложный SQL-запрос и отправляет его на выполнение в СУБД (MS SQL Server или PostgreSQL). В этот момент рабочий поток 1С переходит в состояние синхронного ожидания ответа по сети.
Команда удаления сеанса, отправленная из консоли кластера через менеджер кластера (rmngr), не может прервать исполнение в произвольной точке. Платформа 1С способна обработать сигнал на прерывание только в момент передачи управления между инструкциями встроенного языка. Но пока СУБД выполняет выборку, а драйвер базы данных заблокирован ожиданием сетевых пакетов, управление во встроенный язык не возвращается. Менеджер кластера отправляет запрос в rphost, не получает подтверждения и оставляет сеанс активным.
Следовательно, программные процедуры внутри самой конфигурации 1С вида:
Процедура ЗакрытиеСеансов(ИмяПользователя = Неопределено, backgroundjob = Ложь) Экспорт
// Попытка программного завершения сеанса средствами платформы
КонецПроцедуры
не сработают, так как зависший поток не выполняет код 1С — он просто ожидает окончания запроса на сервере СУБД.
Посмотрим на самое быстрое и эффективное решение проблемы: разорвать ожидание со стороны базы данных. Как только СУБД прекратит выполнять команду или разорвет сокет, рабочий процесс rphost немедленно получит ошибку ввода-вывода (обрыв связи), вернет управление в платформу, и сеанс завершится штатно.
В PostgreSQL предусмотрен максимально мягкий вариант — отмена конкретного запроса без закрытия самого клиентского соединения. Для этого выясним идентификатор процесса (PID) зависшего запроса через представление активности и выполним отмену:
-- Поиск активных долгих запросов
SELECT pid, now() - query_start AS duration, query, state
FROM pg_stat_activity
WHERE state != 'idle'
ORDER BY duration DESC;
-- Мягкая отмена только выполняемого тяжелого запроса
SELECT pg_cancel_backend(pid);
Команда pg_cancel_backend отменяет выполнение запроса, при этом сетевое соединение с rphost сохраняется, а 1С получает понятную ошибку отмены транзакции. Если же сеанс не реагирует на мягкую отмену, можно выполнить полное отключение процесса СУБД с помощью функции SELECT pg_terminate_backend(pid);.
В MS SQL Server мы можем определить идентификатор сессии (SPID), создающей наибольшую нагрузку или удерживающей монопольные блокировки, после чего сбросить ее системной командой KILL:
-- Просмотр выполняющихся запросов и их SPID
SELECT session_id, status, command, start_time, total_elapsed_time
FROM sys.dm_exec_requests
WHERE session_id > 50;
-- Завершение конкретного процесса по его SPID
KILL 78;
После выполнения KILL транзакция в MS SQL откатится, поток в rphost выйдет из ожидания, и зависший сеанс в 1С пропадет сам собой.
Если нет прямого доступа к СУБД, но есть доступ к операционной системе сервера 1С, перезапускать всю службу сервера (ragent) вовсе не требуется. Кластер 1С распределяет соединения между несколькими рабочими процессами rphost.
Разберем по шагам, как локализовать и устранить проблему:
rphost.kill -9 <PID>).Важный момент: служба rmngr автоматически и мгновенно перезапустит упавший рабочий процесс. При этом пострадают исключительно те пользователи, чьи сеансы находились на данном конкретном rphost. Пользователи, работавшие на других рабочих процессах этого же сервера, даже не заметят сбоя.
Иногда графическая оснастка MMC некорректно отправляет команды или сама зависает при опросе перегруженного кластера. В таком случае рассмотрим завершение сеанса через консольную утилиту администрирования rac, работающую через службу ras:
rac session terminate --cluster=<Идентификатор_Кластера> --session=<Идентификатор_Сеанса>
Консольная утилита передает команду серверу напрямую по протоколу TCP без промежуточных графических надстроек, что повышает шансы на успешное удаление сеанса.
Чтобы избежать подобных инцидентов в будущем, рекомендуется настроить защитные механизмы на стороне СУБД и кластера 1С:
statement_timeout (например, ALTER ROLE usr1c SET statement_timeout = '30min';). В этом случае СУБД сама прервет любой запрос, выполняющийся дольше 30 минут, и вернет ошибку в 1С.