Что произойдет с запросом в PostgreSQL, если принудительно завершить сеанс 1С?

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

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

Механизм взаимодействия сервера 1С и PostgreSQL

Для начала проанализируем, как организована связь. Когда пользователь инициирует выполнение запроса, клиент (1cv8.exe) передает команду серверу приложений (rphost). Тот, в свою очередь, выбирает свободное соединение из своего пула и отправляет запрос SQL-серверу. В этот момент между процессом rphost и процессом postgres (backend-процессом) устанавливается активный сетевой диалог. Сервер баз данных начинает выполнять работу: сканирует таблицы, строит индексы в оперативной памяти и формирует временные таблицы.

Если мы убиваем процесс клиента на локальном компьютере, сервер приложений 1С узнает об этом не мгновенно. Еще сложнее ситуация с PostgreSQL: он «считает», что клиент (в данном случае rphost) все еще ждет ответа. Запрос будет выполняться до тех пор, пока база данных не попытается отправить первую порцию данных обратно клиенту и не получит ошибку сетевого сокета, либо пока не сработают специфические внутренние механизмы проверки соединения.

Почему запрос на SQL-сервере не прерывается сразу?

Рассмотрим причины, по которым PostgreSQL продолжает «молотить» данные, даже если в консоли 1С сеанс уже удален:

  1. Отсутствие обратной связи: В протоколе TCP/IP, если одна сторона внезапно исчезает (например, при «убийстве» процесса через kill -9 или диспетчер задач), вторая сторона может не узнать об этом сразу. Соединение переходит в режим ожидания подтверждения.
  2. Буферизация результатов: Пока запрос формирует выборку во временные таблицы (#tt), он ничего не отправляет обратно серверу 1С. Следовательно, PostgreSQL не сталкивается с сетевой ошибкой записи в закрытый сокет.
  3. Инерция рабочего процесса 1С: При удалении сеанса в консоли администрирования 1С, сервер приложений посылает сигнал на отмену, но если поток rphost в этот момент заблокирован ожиданием ответа от СУБД (Socket Read), он может не обработать этот сигнал корректно.

Как отмечают участники обсуждения, на практике часто наблюдается ситуация, когда в консоли 1С сеанса уже нет, а в мониторинге PostgreSQL (pg_stat_activity) мы видим активный запрос, который продолжает потреблять 100% ресурсов процессора или дисковой подсистемы.

Как найти и остановить зависший запрос в PostgreSQL

Выясним, как системный администратор может вмешаться в этот процесс. Самый надежный способ — ручное завершение процесса непосредственно в СУБД. Разберем по шагам, как это сделать:

1. Сначала нам нужно определить идентификатор процесса (PID), который выполняет злополучный запрос. Для этого выполним в любой консоли управления (например, pgAdmin или psql) следующий код:


SELECT pid, usename, datname, query, state, query_start 
FROM pg_stat_activity 
WHERE state != 'idle' 
ORDER BY query_start;

В этом списке мы ищем запросы, которые длятся аномально долго. Вы можете узнать их по тексту SQL-запроса (в нем часто фигурируют имена таблиц 1С, начинающиеся на _InfoReg, _Document и т.д.).

2. После того как PID найден, у нас есть два варианта действий:

Вариант А: Мягкая отмена запроса. Мы посылаем сигнал отмены текущей операции, но само соединение с сервером приложений сохраняется. Это предпочтительный метод.

SELECT pg_cancel_backend(PID_ПРОЦЕССА);

Вариант Б: Жесткое прерывание сессии. Если мягкая отмена не помогает (запрос «залип» в операциях ввода-вывода), мы полностью разрываем соединение с откатом транзакции.

SELECT pg_terminate_backend(PID_ПРОЦЕССА);

Использование настроек PostgreSQL для автоматизации

Проанализируем ситуацию: постоянно мониторить базу вручную невозможно. Для предотвращения появления «зомби-запросов» в современных версиях PostgreSQL (начиная с 14-й и выше) и на уровне операционной системы существуют специальные параметры.

Рассмотрим параметр client_connection_check_interval. Если установить его, например, в значение 5s, PostgreSQL будет каждые 5 секунд проверять, жив ли клиент, который отправил запрос. Если rphost упал или разорвал связь, сервер баз данных сам обнаружит это и прекратит выполнение тяжелого запроса, не дожидаясь его окончания.

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

ALTER ROLE "имя_пользователя_1с" SET statement_timeout = '10min';

Эта настройка принудительно прервет любой запрос, который выполняется дольше 10 минут, защищая сервер от перегрузки.

Проблема временных таблиц и очистки ресурсов

Важно помнить о последствиях внезапного обрыва связи. При работе 1С активно используются временные таблицы. Если соединение между rphost и PostgreSQL было разорвано «грязно» (через убийство процесса), backend-процесс PostgreSQL может удерживать блокировки на системных таблицах или не сразу очистить пространство в pg_temp. В худшем случае это может привести к ошибкам вида #tt не обнаружено или конфликтам при попытке переиспользования этого же соединения из пула сервером 1С. Именно поэтому опытные администраторы рекомендуют после массовых аварийных завершений сеансов проверять состояние СУБД и, при необходимости, выполнять команду VACUUM.

Подведем итог: если вы просто «убили» 1С на клиенте, запрос на SQL-сервере с высокой долей вероятности продолжит выполняться до победного конца. Чтобы реально облегчить жизнь серверу, необходимо либо использовать средства мониторинга СУБД для ручного kill connection, либо настраивать автоматические таймауты в конфигурационных файлах PostgreSQL.

← На главную