Перечисление и переключение баз данных в PostgreSQL: Полное техническое руководство
PostgreSQL управляет несколькими изолированными базами данных в рамках одного экземпляра сервера, каждая из которых имеет собственную схему, роли и привилегии. Чтобы получить список всех баз данных, выполните l внутри psql или выполните запрос SELECT datname FROM pg_catalog.pg_database; из любой сессии. Для переключения между базами данных необходимо открыть новое соединение — PostgreSQL обеспечивает строгую привязку сессии к базе данных без эквивалента команды USE внутри сессии.
В этом руководстве рассматриваются все доступные методы перечисления баз данных PostgreSQL и подключения к ним: от команд psql и запросов к системному каталогу до строк подключения, особенностей pg_hba.conf и шаблонов работы с несколькими базами данных, применяемых в производственных средах.
Почему переключение баз данных в PostgreSQL работает иначе
Большинство разработчиков, пришедших из MySQL, ожидают команду USE database_name;. PostgreSQL намеренно её не предоставляет. Каждая сессия PostgreSQL привязывается ровно к одной базе данных в момент подключения, и эта привязка неизменна на протяжении всего времени жизни сессии. Это архитектурное решение обусловлено моделью процессов PostgreSQL: серверный процесс (postgres) загружает системный каталог базы данных в общую память при запуске, и переключение каталогов в середине сессии в любом случае потребовало бы полного перезапуска процесса.
Понимание этого ограничения с самого начала позволяет избежать многочасовой отладки и определяет подход к проектированию инструментов для работы с несколькими базами данных, пулов соединений и конфигураций приложений.
Получение списка всех баз данных в PostgreSQL
Метод 1: Мета-команда l в psql
Самый быстрый способ перечислить базы данных — мета-команда l (псевдоним: list) в интерактивной сессии psql.
psql -U postgresПосле подключения:
lРезультатом будет отформатированная таблица, аналогичная следующей:
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
myapp_db | appuser | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
analytics | analyst | UTF8 | en_US.UTF-8 | en_US.UTF-8 | analyst=CTc/analyst
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |Столбцы содержат больше информации, чем просто имена: Encoding важна при миграции данных между серверами, Collate влияет на порядок сортировки и поведение индексов, а Access privileges используют нотацию ACL PostgreSQL (C = CONNECT, T = TEMPORARY, c = CREATE).
Для получения расширенных сведений, включая табличное пространство и ограничения на количество соединений, используйте:
l+Метод 2: Запрос к системному каталогу pg_database
Для написания скриптов, мониторинга или интроспекции на уровне приложения выполните запрос непосредственно к представлению pg_catalog.pg_database. Это работает из любой базы данных в кластере, поскольку системные каталоги видны глобально.
SELECT
datname AS database_name,
pg_catalog.pg_get_userbyid(datdba) AS owner,
pg_encoding_to_char(encoding) AS encoding,
datcollate AS collation,
datctype AS ctype,
datconnlimit AS connection_limit,
pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(datname)) AS size
FROM pg_catalog.pg_database
WHERE datistemplate = false
ORDER BY datname;Фильтрация datistemplate = false исключает template0 и template1 из результатов — это системные шаблоны, а не рабочие базы данных. Столбец datconnlimit критически важен в общих средах: значение -1 означает отсутствие ограничений, тогда как любое положительное целое число ограничивает количество одновременных подключений к этой базе данных.
Совет для производственной среды: Добавьте pg_database_size() в запросы мониторинга. База данных, незаметно превышающая ёмкость табличного пространства, — распространённая причина ошибок записи, которые сложно диагностировать постфактум.
Метод 3: Получение списка баз данных без входа в psql
Для shell-скриптов и конвейеров автоматизации можно получить список баз данных без входа в интерактивную сессию:
psql -U postgres -c "l"Или для чистого, пригодного для парсинга вывода:
psql -U postgres -t -c "SELECT datname FROM pg_database WHERE datistemplate = false;"Флаг -t подавляет заголовки столбцов и счётчики строк, возвращая только необработанные значения — идеально подходит для передачи в grep, awk или массивы Bash.
Для экспорта списка в файл:
psql -U postgres -t -A -c "SELECT datname FROM pg_database WHERE datistemplate = false;" > db_list.txt-A отключает выравнивание столбцов, выводя по одному имени базы данных на строку.
Переключение между базами данных в PostgreSQL
Поскольку переключение баз данных внутри активной сессии невозможно, правильный подход — завершить текущее соединение и установить новое, указав нужную базу данных. Существует несколько эффективных способов сделать это.
Метод 1: Выход и повторное подключение из оболочки
Внутри psql завершите текущую сессию:
q
Затем подключитесь к целевой базе данных:
psql -U postgres -d target_database
Метод 2: Использование c (Connect) внутри psql
Это наиболее практичный метод для интерактивной работы. Мета-команда c закрывает текущее соединение и открывает новое к указанной базе данных — всё в рамках одной терминальной сессии.
c target_database
Можно также одновременно сменить пользователя и хост:
c target_database admin_user localhost 5432
Синтаксис: c [database [username [host [port]]]]При выполнении c psql отобразит подтверждение:
You are now connected to database "target_database" as user "postgres".Важный граничный случай: Если целевая база данных не существует или текущий пользователь не имеет привилегии CONNECT, команда c завершится ошибкой и вернёт вас к предыдущему соединению. Это безопаснее, чем кажется — вы не останетесь без соединения, однако в скриптах необходимо обрабатывать этот случай, проверяя код завершения.
Метод 3: Подключение от имени другого пользователя
Для подключения к базе данных под определённой ролью:
psql -d myapp_db -U appuser -h localhost -p 5432Или с использованием сокращения c внутри существующей сессии:
c myapp_db appuserЭто особенно полезно при тестировании политик безопасности на уровне строк (RLS) или проверке того, что пользователи приложения не могут получить доступ к таблицам за пределами своей схемы.
Метод 4: Использование строк подключения (формат URI)
PostgreSQL поддерживает формат URI libpq для подключения, который объединяет все параметры соединения в одну строку. Это предпочтительный метод для конфигурации приложений, конвейеров CI/CD и инструментов инфраструктуры как кода.
psql "postgresql://appuser:password@localhost:5432/myapp_db"Или с использованием схемы postgres:// (оба варианта допустимы):
psql "postgres://appuser:password@db.example.com:5432/analytics?sslmode=require"Параметр ?sslmode=require обеспечивает шифрование TLS для соединения — обязательное требование для любой базы данных, доступной за пределами localhost. Если вы размещаете PostgreSQL на VPS или выделенном сервере, всегда используйте строки подключения с sslmode=require или sslmode=verify-full и действующим SSL-сертификатом.
Примечательные параметры URI подключения:
| Параметр | Назначение | Пример значения |
|---|---|---|
sslmode | Уровень применения TLS | require, verify-full |
connect_timeout | Секунды до сбоя соединения | 10 |
application_name | Идентифицирует клиента в pg_stat_activity | myapp_worker |
options | Передача серверных параметров GUC | -c search_path=myschema |
Метод 5: Использование psql с переменными окружения
Для повторных подключений к одному кластеру задайте переменные окружения, чтобы не вводить учётные данные каждый раз:
export PGHOST=localhost
export PGPORT=5432
export PGUSER=postgres
export PGPASSWORD=secret # Use .pgpass file in production instead
export PGDATABASE=myapp_db
psqlВ производственной среде используйте файл .pgpass вместо PGPASSWORD, чтобы не раскрывать учётные данные в истории оболочки или списках процессов:
# ~/.pgpass format: hostname:port:database:username:password
localhost:5432:myapp_db:appuser:strongpasswordУстановите правильные разрешения, иначе PostgreSQL проигнорирует файл:
chmod 600 ~/.pgpassСравнение методов переключения баз данных
| Метод | Контекст | Требует нового процесса | Поддерживает смену пользователя | Поддаётся автоматизации |
|---|---|---|---|---|
q + psql -d | Оболочка | Да | Да | Да |
c dbname | Интерактивный psql | Нет (psql обрабатывает это) | Да | Ограниченно |
| URI подключения | Оболочка / Приложение | Да | Да | Да |
| Переменные окружения | Оболочка | Да | Да | Да |
| GUI pgAdmin | GUI-клиент | Нет | Да | Нет |
| Пул соединений (PgBouncer) | Приложение | Нет | Зависит от режима | Да |
Эффективное управление несколькими подключениями к базам данных
Использование pgAdmin для навигации через GUI
pgAdmin отображает все базы данных под каждым зарегистрированным сервером в дереве объектов слева. При нажатии на базу данных и открытии инструмента запросов все запросы автоматически выполняются в контексте этой базы данных. Это удобно для исследовательской работы, но не подходит для автоматизации.
Предупреждение: pgAdmin поддерживает отдельные слоты соединений для каждой базы данных. Если на вашем сервере PostgreSQL установлено низкое значение max_connections (по умолчанию 100), открытие множества баз данных в pgAdmin может исчерпать пул соединений ещё до запуска вашего приложения.
Использование PgBouncer для пулинга соединений
В производственных средах с частым переключением баз данных пулер соединений, такой как PgBouncer, значительно снижает накладные расходы. PgBouncer работает в трёх режимах:
- Режим сессии: Одно серверное соединение на клиентскую сессию. Функционально эквивалентен прямым подключениям.
- Режим транзакции: Серверное соединение удерживается только во время транзакции. Наиболее эффективен для OLTP-нагрузок.
- Режим оператора: Соединение возвращается после каждого оператора. Несовместим с многооператорными транзакциями.
При запуске нескольких баз данных приложений на одном экземпляре PostgreSQL — распространённая схема на VPS-хостинге или VPS с cPanel — PgBouncer в режиме транзакции может сократить количество активных серверных процессов на порядок.
Межбазовые запросы с dblink и postgres_fdw
Поскольку сессии привязаны к базе данных, для запроса данных из разных баз данных требуется расширение. PostgreSQL предоставляет два варианта:
dblink — старый процедурный подход:
SELECT * FROM dblink(
'dbname=analytics user=analyst host=localhost',
'SELECT user_id, event_count FROM events WHERE date = current_date'
) AS remote(user_id INT, event_count BIGINT);postgres_fdw — современная обёртка внешних данных, соответствующая стандартам:
CREATE EXTENSION postgres_fdw;
CREATE SERVER analytics_server
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host 'localhost', dbname 'analytics', port '5432');
CREATE USER MAPPING FOR appuser
SERVER analytics_server
OPTIONS (user 'analyst', password 'secret');
CREATE FOREIGN TABLE remote_events (
user_id INT,
event_count BIGINT
)
SERVER analytics_server
OPTIONS (schema_name 'public', table_name 'events');После настройки remote_events ведёт себя как локальная таблица. postgres_fdw поддерживает проталкивание предикатов, то есть условия WHERE выполняются на удалённом сервере, а не локально — критически важное отличие для производительности при работе с большими наборами данных.
Системные базы данных: что нельзя трогать
PostgreSQL поставляется с четырьмя базами данных в каждом новом кластере:
| База данных | Назначение | Безопасно подключаться? | Безопасно изменять? |
|---|---|---|---|
postgres | База данных администратора по умолчанию | Да | С осторожностью |
template1 | Шаблон для CREATE DATABASE | Да | Да, изменения распространяются |
template0 | Чистый базовый шаблон | Редко | Нет |
pg_catalog | Не база данных, а схема | Н/П | Никогда |
template1 клонируется при каждом выполнении CREATE DATABASE без указания шаблона. Если установить расширения или создать схемы в template1, каждая новая база данных унаследует их. Это полезно для стандартизации сред, но опасно при случайном изменении.
template0 существует как чистый резервный вариант. Это единственный шаблон, который можно использовать при восстановлении архива pg_dump с другой кодировкой или локалью, поскольку в нём нет пользовательских объектов, которые могли бы вызвать конфликты.
Привилегии, pg_hba.conf и ошибки подключения
Распространённый источник путаницы при переключении баз данных — различие между привилегиями на уровне ролей PostgreSQL и правилами аутентификации pg_hba.conf. Оба условия должны разрешать подключение независимо друг от друга.
Проверка на уровне роли: Роль должна иметь привилегию CONNECT на целевую базу данных:
GRANT CONNECT ON DATABASE target_database TO appuser;Проверка pg_hba.conf: Файл аутентификации на основе хоста (/etc/postgresql/15/main/pg_hba.conf в Debian/Ubuntu) должен содержать соответствующее правило для пользователя, базы данных и адреса источника. Типичная запись:
# TYPE DATABASE USER ADDRESS METHOD
host myapp_db appuser 10.0.0.0/8 scram-sha-256После редактирования pg_hba.conf перезагрузите конфигурацию без перезапуска сервера:
sudo systemctl reload postgresqlИли изнутри psql:
SELECT pg_reload_conf();Типичная ошибка: Пользователь имеет привилегию CONNECT на уровне SQL, но в pg_hba.conf нет соответствующего правила. Сообщение об ошибке (FATAL: no pg_hba.conf entry for host) является явным, однако разработчики часто игнорируют этот файл, ожидая, что разрешения базы данных управляются исключительно через SQL.
Практическая матрица принятия решений
Используйте этот контрольный список для выбора подходящего метода подключения в вашем сценарии:
- Интерактивное исследование на локальной машине разработки: Используйте
c dbnameвнутриpsql. Быстро, без нового процесса. - Shell-скрипт, перебирающий несколько баз данных: Используйте
psql -U postgres -d $dbname -c "..."в цикле с-t -Aдля чистого вывода. - Приложение, подключающееся к одной базе данных: Используйте URI подключения с
sslmode=requireи пулом соединений (PgBouncer или встроенный пулинг драйвера). - Приложение, которому нужны данные из двух баз данных: Реализуйте
postgres_fdwна основной базе данных вместо управления двумя отдельными пулами соединений в коде приложения. - Проверка изоляции RLS или привилегий: Используйте
c dbname role_nameдля имитации целевой роли без выхода изpsql. - Автоматизированное развёртывание / инфраструктура как код: Используйте переменные окружения или
.pgpassс сервисной учётной записью; никогда не встраивайте учётные данные в скрипты. - Высоконагруженная производственная среда: Разверните PgBouncer в режиме транзакции между приложением и PostgreSQL. На выделенном сервере настройте
max_connectionsвpostgresql.confв соответствии с объёмом памяти вашего оборудования (каждый серверный процесс использует приблизительно 5–10 МБ RAM). - Многопользовательский SaaS с отдельными базами данных для каждого клиента: Рассмотрите многопользовательскую архитектуру на основе схем в рамках одной базы данных вместо отдельных баз данных для каждого клиента, чтобы избежать фрагментации пула соединений и упростить стратегии резервного копирования.
Для команд, запускающих PostgreSQL совместно с веб-приложениями, сочетание сервера базы данных с правильно настроенной средой виртуального хостинга или VPS и зарегистрированным доменом для уровня приложения формирует стандартный производственный стек.
Часто задаваемые вопросы
Можно ли переключить базу данных, не закрывая сессию psql?
Да. Используйте мета-команду c target_database внутри psql. Она закрывает текущее серверное соединение и открывает новое к указанной базе данных — всё в рамках одной терминальной сессии. В той же команде можно дополнительно указать другого пользователя, хост и порт.
Почему в PostgreSQL нет команды USE, как в MySQL?
Архитектура PostgreSQL привязывает серверный процесс к одной базе данных при запуске. Системный каталог базы данных загружается в общую память для этого процесса, и переключение каталогов в середине сессии архитектурно эквивалентно запуску нового процесса. Команда c в psql является практическим эквивалентом — она просто делает перезапуск процесса прозрачным для пользователя.
Как выполнить запрос к данным из двух разных баз данных PostgreSQL одновременно?
Используйте расширение postgres_fdw для создания внешнего сервера и внешних таблиц, отображающих удалённую базу данных. После настройки можно объединять локальные и удалённые таблицы в одном запросе. Для разовых запросов dblink проще, но менее производителен и сложнее в обслуживании.
Что произойдёт, если подключиться к template1 и изменить её?
Любые объекты, созданные в template1 — таблицы, расширения, схемы — будут клонированы в каждую новую базу данных, созданную с помощью CREATE DATABASE (если только TEMPLATE template0 не указан явно). Иногда это делается намеренно (например, предустановка uuid-ossp или pgcrypto), однако случайные изменения могут повредить все впоследствии создаваемые базы данных.
Как узнать, к какой базе данных подключена текущая сессия psql?
Выполните следующее внутри psql:
SELECT current_database();Или проверьте само приглашение psql — по умолчанию оно отображает dbname=# (суперпользователь) или dbname=> (обычный пользователь), где dbname — активная база данных.
