
При работе SAS с PostgreSQL соединение с базой данных часто сохраняется дольше, чем ожидается. Это происходит при использовании LIBNAME, PROC SQL и pass-through запросов, когда сессия в PostgreSQL остаётся активной до завершения SAS-процесса или освобождения библиотеки. В результате в pg_stat_activity видны «висящие» подключения, блокирующие обновления схем, резервное копирование или DDL-операции.
Проблема усугубляется в средах с пакетной обработкой, SAS Grid или SAS Enterprise Guide, где один пользователь может открыть несколько сессий к PostgreSQL за короткое время. Без явного закрытия соединения PostgreSQL продолжает удерживать backend-процесс, потребляя память и слот подключения. При достижении max_connections новые клиенты получают отказ, хотя реальная работа уже завершена.
Корректное завершение подключения из SAS требует понимания, какой механизм его открыл. LIBNAME использует длительное соединение, связанное с библиотекой. PROC SQL открывает соединение на время SQL-сессии, но не всегда закрывает его сразу при ошибках. Pass-through запросы могут оставлять соединение активным до выполнения явной команды завершения.
В статье разобраны прикладные способы закрытия подключения PostgreSQL из SAS: освобождение библиотеки, завершение SQL-сессии, обработка аварийных сценариев и проверка результата на стороне PostgreSQL. Все примеры ориентированы на реальные рабочие ситуации, где контроль соединений влияет на стабильность и предсказуемость работы системы.
Как создаётся соединение с PostgreSQL в SAS через LIBNAME

При использовании оператора LIBNAME SAS открывает соединение с PostgreSQL в момент первого обращения к библиотеке, а не в момент объявления. Пока библиотека не используется, сессия на стороне PostgreSQL не создаётся. Как только выполняется чтение или запись таблицы, SAS инициирует TCP-соединение и регистрирует backend-процесс в pg_stat_activity.
Соединение, созданное через LIBNAME, привязывается к SAS-сессии и сохраняется между шагами DATA и процедурами. Даже после завершения конкретного шага SAS не разрывает связь с PostgreSQL, так как библиотека остаётся активной. Это поведение часто воспринимается как утечка подключений, хотя фактически сессия удерживается намеренно.
Параметры подключения передаются напрямую драйверу: server, port, database, user, password. SAS не открывает отдельные соединения для каждой таблицы – одна библиотека соответствует одной сессии PostgreSQL. Повторное объявление LIBNAME с тем же именем не пересоздаёт подключение, если библиотека уже используется.
Если SAS-код выполняется в интерактивной среде, соединение через LIBNAME может существовать часами, пока пользователь не завершит сеанс или явно не освободит библиотеку. В пакетных заданиях соединение закрывается только при штатном завершении программы, поэтому аварийное прерывание часто оставляет активные backend-процессы в PostgreSQL.
Понимание этого механизма позволяет осознанно управлять подключениями: любое действие с таблицами библиотеки продлевает жизнь сессии, а отсутствие явного освобождения библиотеки гарантирует, что PostgreSQL будет считать клиента активным независимо от того, выполняются ли запросы в данный момент.
Какие ресурсы PostgreSQL остаются занятыми после выполнения SAS-кода
После завершения SAS-шагов соединение с PostgreSQL может сохраняться, удерживая отдельный backend-процесс. Этот процесс отображается в pg_stat_activity со статусом idle или idle in transaction, продолжая потреблять память для сессионного контекста и рабочие структуры планировщика запросов.
Если SAS выполнял операции чтения или записи, PostgreSQL оставляет за соединением файловые дескрипторы таблиц и индексов, а также записи в системных кэшах. При большом количестве таких подключений растёт нагрузка на shared buffers и увеличивается время обслуживания новых сессий.
Наиболее проблемный сценарий связан с состоянием idle in transaction. Он возникает, когда SAS открывает транзакцию и не завершает её явным образом. В этом случае удерживаются MVCC-снимки, что блокирует очистку «мёртвых» строк и приводит к росту таблиц и индексов, даже при отсутствии активных запросов.
Соединение, оставшееся после SAS-кода, продолжает занимать слот подключения. При достижении значения max_connections PostgreSQL отказывает новым клиентам, включая сервисные задачи и административные подключения, хотя фактической нагрузки может не быть.
Также сохраняются блокировки на уровне транзакций и схем, если SAS выполнял DDL или временные таблицы. Такие блокировки мешают обновлению структуры базы и могут привести к ожиданиям в других сессиях. Контроль этих ресурсов возможен только при своевременном закрытии соединения или принудительном завершении backend-процесса.
Как корректно закрыть подключение PostgreSQL при использовании LIBNAME
Соединение PostgreSQL, созданное через LIBNAME, закрывается только при освобождении библиотеки или завершении SAS-сессии. Простое окончание DATA step или процедуры не разрывает связь с базой. Пока библиотека объявлена, PostgreSQL считает клиента активным.
Единственный штатный способ закрыть соединение – выполнить команду LIBNAME имя_библиотеки CLEAR;. После её выполнения SAS освобождает библиотеку, отправляет драйверу сигнал на закрытие сессии и backend-процесс исчезает из pg_stat_activity. Команду следует размещать сразу после последнего обращения к таблицам PostgreSQL.
Если LIBNAME используется в нескольких шагах, очистку нельзя выполнять раньше времени. Любая попытка обращения к таблице после CLEAR приведёт к ошибке, но не восстановит прежнее соединение. Для повторной работы потребуется новое объявление LIBNAME и новая сессия PostgreSQL.
В интерактивных средах важно учитывать, что закрытие программы или вкладки не всегда означает завершение SAS-сессии. Библиотека может оставаться активной до выхода пользователя из среды. В таких случаях LIBNAME CLEAR – единственный способ гарантированно освободить соединение без ожидания тайм-аутов на стороне PostgreSQL.
В пакетных заданиях команду очистки рекомендуется выполнять даже при штатном завершении программы. Это снижает риск сохранения соединения при частичном падении кода и упрощает контроль числа активных backend-процессов в PostgreSQL.
Как завершить соединение PostgreSQL при работе с PROC SQL в SAS
При использовании PROC SQL в SAS соединение с PostgreSQL создаётся автоматически при первом обращении к базе через pass-through или LIBNAME. После выполнения SQL-запроса соединение не всегда закрывается, особенно если используется implicit connection через LIBNAME.
Для явного разрыва соединения рекомендуется использовать pass-through с закрытием сессии через команду DISCONNECT FROM POSTGRES;. Например, блок кода:
proc sql;
connect to postgres (user=»имя» password=»пароль» server=»сервер» database=»база»);
execute (ваш SQL-запрос) by postgres;
disconnect from postgres;
quit;
DISCONNECT завершает backend-процесс на стороне PostgreSQL, освобождает слоты подключения и снимает удерживаемые транзакции. Без этой команды соединение остаётся активным, отображаясь в pg_stat_activity со статусом idle или idle in transaction.
Если используется implicit connection через LIBNAME, DISCONNECT не требуется, но для контроля ресурсов лучше комбинировать PROC SQL с LIBNAME CLEAR после выполнения всех SQL-операций. Это гарантирует, что сессия PostgreSQL будет полностью завершена.
Для длительных или пакетных задач стоит проверять наличие активных соединений после выполнения PROC SQL и освобождать их через CLEAR или отдельные DISCONNECT-команды, чтобы избежать блокировок и превышения max_connections на сервере.
Как закрыть подключение при ошибке выполнения SAS-процедуры

При сбое SAS-процедуры соединение с PostgreSQL часто остаётся активным. В таких случаях backend-процесс продолжает существовать, удерживая транзакции и слоты подключения. Ошибки могут возникать из-за синтаксиса SQL, недоступности таблиц или превышения лимитов памяти на сервере.
Для завершения соединения после ошибки рекомендуется использовать LIBNAME CLEAR или DISCONNECT FROM POSTGRES в отдельном блоке кода, обрабатываемом после завершения процедуры. Такой подход позволяет гарантированно освободить ресурсы независимо от того, завершилась ли процедура успешно.
Пример обработки ошибок в PROC SQL с pass-through:
proc sql;
connect to postgres (user=»имя» password=»пароль» server=»сервер» database=»база»);
%try;
execute (ваш SQL-запрос) by postgres;
%catch;
disconnect from postgres;
%end;
quit;
Если используется LIBNAME, даже при аварийном завершении программы стоит добавить отдельный шаг очистки библиотеки: LIBNAME имя_библиотеки CLEAR;. Это предотвращает зависание backend-процессов и освобождает удерживаемые блокировки на уровне транзакций и схем.
Регулярная проверка pg_stat_activity после выполнения SAS-кода позволяет выявлять зависшие подключения и своевременно их закрывать, снижая риск превышения max_connections и блокировок в PostgreSQL.
Как проверить, что соединение PostgreSQL действительно закрыто
После выполнения команд LIBNAME CLEAR или DISCONNECT важно убедиться, что соединение с PostgreSQL действительно завершено. Несколько методов позволяют проверить статус сессии:
- Использовать системный каталог pg_stat_activity. Выполните запрос:
SELECT pid, usename, state, query FROM pg_stat_activity WHERE usename = ‘имя_пользователя’;
- Если после закрытия соединения отсутствуют процессы с вашим пользователем и статус idle или idle in transaction, соединение успешно завершено.
- Проверить наличие активных транзакций через SELECT * FROM pg_locks;. Отсутствие блокировок, связанных с вашей сессией, указывает на закрытие транзакций.
- Для LIBNAME можно в SAS выполнить повторное обращение к библиотеке после CLEAR. Ошибка «LIBRARY not assigned» подтверждает, что сессия больше не активна.
Дополнительно полезно проверять использование слотов подключения:
- В PostgreSQL параметр max_connections позволяет отслеживать количество текущих сессий.
- Сравнение значений до и после выполнения CLEAR или DISCONNECT показывает, освобождён ли слот.
Регулярная проверка помогает контролировать количество активных backend-процессов и предотвращает ситуации, когда зависшие соединения блокируют выполнение новых задач или повышают нагрузку на сервер.
Как управлять пулом подключений PostgreSQL в среде SAS

В SAS несколько параллельных процессов могут использовать один и тот же PostgreSQL, создавая множество соединений. Контроль пула подключений важен для предотвращения превышения max_connections и зависания backend-процессов.
Основные методы управления:
| Метод | Описание | Рекомендации |
|---|---|---|
| LIBNAME CLEAR | Освобождает библиотеку и закрывает соответствующую сессию PostgreSQL | Выполнять сразу после завершения всех операций с таблицами. Не оставлять библиотеки открытыми между шагами. |
| DISCONNECT FROM POSTGRES | Закрывает pass-through соединение, созданное в PROC SQL | Использовать в блоках кода, где возможны ошибки или повторные вызовы SQL-запросов. Проверять состояние после DISCONNECT. |
| Системная проверка pg_stat_activity | Позволяет отслеживать активные backend-процессы и их статус | Регулярно сверять количество соединений и освобождать зависшие процессы через CLEAR или DISCONNECT. |
| Пакетная обработка с тайм-аутами | Настройка параметров соединений на стороне PostgreSQL | Использовать idle_in_transaction_timeout и statement_timeout, чтобы автоматизировать завершение зависших сессий. |
Эти меры позволяют поддерживать пул подключений на контролируемом уровне, снижать риск блокировок и обеспечивать стабильную работу SAS при интенсивном взаимодействии с PostgreSQL.
Типовые причины зависших подключений PostgreSQL из SAS и способы их устранения

Зависшие подключения возникают, когда SAS оставляет активные сессии PostgreSQL без закрытия. Основные причины и способы их устранения:
- Открытые библиотеки LIBNAME без CLEAR
- Причина: библиотека остаётся активной между шагами DATA или PROC, удерживая соединение.
- Устранение: после завершения всех операций выполнить LIBNAME имя_библиотеки CLEAR;.
- Pass-through соединения в PROC SQL без DISCONNECT
- Причина: соединение остаётся открытым после выполнения SQL-запроса.
- Устранение: использовать DISCONNECT FROM POSTGRES; после выполнения всех запросов.
- Аварийное завершение SAS-процедур
- Причина: ошибки или падения кода не закрывают сессии.
- Устранение: добавлять отдельный шаг очистки через LIBNAME CLEAR или DISCONNECT в блоке после обработки ошибок.
- Длительные транзакции
- Причина: SAS открывает транзакцию и не завершает её, оставаясь в состоянии idle in transaction.
- Устранение: проверять транзакции в pg_stat_activity и завершать их вручную или через DISCONNECT.
- Параллельные задания и пакетная обработка
- Причина: множество одновременно запущенных SAS-процессов создают пул соединений, превышающий max_connections.
- Устранение: контролировать количество параллельных процессов, освобождать библиотеки и соединения после завершения задач.
Регулярная проверка pg_stat_activity и систематическое закрытие соединений после каждой операции позволяет минимизировать зависшие сессии и освобождать ресурсы PostgreSQL.
Вопрос-ответ:
Почему соединение с PostgreSQL остаётся активным после выполнения LIBNAME в SAS?
Соединение через LIBNAME создаётся при первом обращении к таблицам и сохраняется до освобождения библиотеки. Даже после завершения DATA step или PROC, SAS продолжает удерживать сессию PostgreSQL, что отображается в pg_stat_activity. Для закрытия соединения необходимо выполнить команду LIBNAME имя_библиотеки CLEAR;, чтобы разорвать сессию и освободить backend-процесс на сервере.
Как проверить, что соединение PostgreSQL действительно закрыто после DISCONNECT в PROC SQL?
После выполнения DISCONNECT можно проверить состояние сессии через системный каталог pg_stat_activity. Если процесс пользователя отсутствует или не имеет статуса idle или idle in transaction, соединение закрыто. Дополнительно можно сверить количество активных соединений до и после DISCONNECT и убедиться, что слоты подключения освобождены.
Что делать, если SAS аварийно завершает процедуру и соединение остаётся зависшим?
В таких случаях рекомендуется добавлять отдельный шаг очистки после процедуры. Для LIBNAME использовать CLEAR, для pass-through запросов через PROC SQL — DISCONNECT FROM POSTGRES. Также полезно периодически проверять pg_stat_activity и при необходимости завершать зависшие backend-процессы вручную, чтобы освободить транзакции и слоты подключения.
Как управлять пулом подключений PostgreSQL при работе с несколькими SAS-процессами одновременно?
Каждый параллельный SAS-процесс может создавать собственное соединение с PostgreSQL, что увеличивает нагрузку на сервер. Для контроля рекомендуется: ограничивать количество параллельных заданий, после выполнения SQL-запросов закрывать соединения через DISCONNECT, освобождать библиотеки через LIBNAME CLEAR и отслеживать активные процессы в pg_stat_activity. Это предотвращает превышение параметра max_connections и блокировки новых соединений.
Почему статус «idle in transaction» опасен и как с ним работать в SAS?
Статус idle in transaction возникает, когда SAS открывает транзакцию и не завершает её. В PostgreSQL это удерживает MVCC-снимки и блокировки на уровне строк и схем. Чтобы избежать последствий, после выполнения операций необходимо завершать транзакцию или использовать DISCONNECT для pass-through соединений. Для LIBNAME рекомендуется выполнять CLEAR, чтобы сессия полностью закрывалась и не блокировала дальнейшие операции.
Как правильно завершить соединение PostgreSQL после выполнения кода в SAS, чтобы не оставалось зависших сессий?
Чтобы соединение PostgreSQL полностью закрылось, необходимо учитывать, какой метод доступа использовался. Если подключение было через LIBNAME, следует выполнить команду LIBNAME имя_библиотеки CLEAR; сразу после последнего обращения к таблицам. Это освобождает библиотеку и закрывает backend-процесс на сервере. При использовании PROC SQL с pass-through запросами нужно после всех операций добавить DISCONNECT FROM POSTGRES;, что завершит транзакцию и освободит слот подключения. После выполнения этих действий рекомендуется проверить состояние сессий через pg_stat_activity, чтобы убедиться, что не осталось процессов с статусом idle или idle in transaction. Такой подход предотвращает зависание соединений и блокировки при последующих операциях.
