Wyświetlanie i przełączanie baz danych w PostgreSQL: Kompletny przewodnik techniczny
PostgreSQL zarządza wieloma izolowanymi bazami danych w ramach jednej instancji serwera, z których każda ma własny schemat, role i uprawnienia. Aby wyświetlić listę wszystkich baz danych, uruchom l wewnątrz psql lub wykonaj zapytanie SELECT datname FROM pg_catalog.pg_database; z dowolnej sesji. Aby przełączyć bazę danych, musisz otworzyć nowe połączenie — PostgreSQL wymusza ścisłe powiązanie sesji z bazą danych, bez odpowiednika polecenia USE w ramach sesji.
Ten przewodnik omawia wszystkie dostępne metody wyliczania i łączenia się z bazami danych PostgreSQL, od poleceń psql i zapytań do katalogu systemowego, po ciągi połączeń, zagadnienia pg_hba.conf oraz wzorce pracy z wieloma bazami danych stosowane w środowiskach produkcyjnych.
Dlaczego przełączanie baz danych w PostgreSQL działa inaczej
Większość programistów przychodzących z MySQL spodziewa się polecenia USE database_name;. PostgreSQL celowo je pomija. Każda sesja PostgreSQL jest powiązana dokładnie z jedną bazą danych w momencie nawiązania połączenia, a to powiązanie jest niezmienne przez cały czas trwania sesji. Jest to decyzja architektoniczna zakorzeniona w modelu procesów PostgreSQL: proces backendowy (postgres) ładuje katalog systemowy bazy danych do pamięci współdzielonej podczas uruchamiania, a przełączanie katalogów w trakcie sesji i tak wymagałoby pełnego restartu procesu.
Zrozumienie tego ograniczenia z góry pozwala uniknąć godzin debugowania i kształtuje sposób projektowania narzędzi wielobazodanowych, pul połączeń i konfiguracji aplikacji.
Wyświetlanie listy wszystkich baz danych w PostgreSQL
Metoda 1: Meta-polecenie l w psql
Najszybszym sposobem wyliczenia baz danych jest meta-polecenie l (alias: list) wewnątrz interaktywnej sesji psql.
psql -U postgresPo nawiązaniu połączenia:
lWynikiem jest sformatowana tabela podobna do:
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 |Kolumny ujawniają więcej niż tylko nazwy: Encoding ma znaczenie przy migracji danych między serwerami, Collate wpływa na kolejność sortowania i zachowanie indeksów, a Access privileges używa notacji ACL PostgreSQL (C = CONNECT, T = TEMPORARY, c = CREATE).
Aby uzyskać rozszerzone szczegóły, w tym przestrzeń tabel i limity połączeń, użyj:
l+Metoda 2: Zapytanie do katalogu systemowego pg_database
Do skryptowania, monitorowania lub introspekcji na poziomie aplikacji wykonaj zapytanie bezpośrednio do widoku pg_catalog.pg_database. Działa to z dowolnej bazy danych w klastrze, ponieważ katalogi systemowe są widoczne globalnie.
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;Filtrowanie datistemplate = false wyklucza template0 i template1 z wyników — są to szablony systemowe, a nie operacyjne bazy danych. Kolumna datconnlimit jest kluczowa w środowiskach współdzielonych: wartość -1 oznacza brak limitu, podczas gdy każda dodatnia liczba całkowita ogranicza liczbę jednoczesnych połączeń z tą bazą danych.
Wskazówka produkcyjna: Dodaj pg_database_size() do zapytań monitorujących. Baza danych po cichu przekraczająca pojemność przestrzeni tabel jest częstą przyczyną błędów zapisu, które są trudne do zdiagnozowania po fakcie.
Metoda 3: Wyświetlanie listy baz danych bez wchodzenia do psql
W przypadku skryptów powłoki i potoków automatyzacji można pobrać listę baz danych bez wchodzenia do sesji interaktywnej:
psql -U postgres -c "l"Lub dla czystych, przetwarzalnych przez skrypty danych wyjściowych:
psql -U postgres -t -c "SELECT datname FROM pg_database WHERE datistemplate = false;"Flaga -t pomija nagłówki kolumn i liczby wierszy, zwracając tylko surowe wartości — idealne do przekazywania potokiem do grep, awk lub tablic Bash.
Aby wyeksportować listę do pliku:
psql -U postgres -t -A -c "SELECT datname FROM pg_database WHERE datistemplate = false;" > db_list.txt-A wyłącza wyrównanie kolumn, generując jedną nazwę bazy danych w każdym wierszu.
Przełączanie między bazami danych w PostgreSQL
Ponieważ nie można przełączać baz danych w ramach aktywnej sesji, właściwym podejściem jest zakończenie bieżącego połączenia i nawiązanie nowego, skierowanego do żądanej bazy danych. Istnieje kilka sposobów, aby zrobić to efektywnie.
Metoda 1: Wyjście i ponowne połączenie z powłoki
Wewnątrz psql zakończ bieżącą sesję:
q
Następnie połącz się z docelową bazą danych:
psql -U postgres -d target_database
Metoda 2: Użycie c (Connect) wewnątrz psql
Jest to najbardziej praktyczna metoda do pracy interaktywnej. Meta-polecenie c zamyka bieżące połączenie i otwiera nowe do wskazanej bazy danych — wszystko w ramach tej samej sesji terminala.
c target_database
Można również jednocześnie zmienić użytkownika i hosta:
c target_database admin_user localhost 5432
Składnia: c [database [username [host [port]]]]Po uruchomieniu c, psql wyświetli potwierdzenie:
You are now connected to database "target_database" as user "postgres".Ważny przypadek brzegowy: Jeśli docelowa baza danych nie istnieje lub bieżący użytkownik nie ma uprawnienia CONNECT, polecenie c zakończy się niepowodzeniem i powróci do poprzedniego połączenia. Jest to bezpieczniejsze niż się wydaje — nie zostaniesz bez połączenia, ale w skryptach musisz obsłużyć ten przypadek, sprawdzając status wyjścia.
Metoda 3: Łączenie jako inny użytkownik
Aby połączyć się z bazą danych w ramach określonej roli:
psql -d myapp_db -U appuser -h localhost -p 5432Lub używając skrótu c wewnątrz istniejącej sesji:
c myapp_db appuserJest to szczególnie przydatne podczas testowania polityk zabezpieczeń na poziomie wierszy (RLS) lub weryfikowania, że użytkownicy aplikacji nie mają dostępu do tabel poza swoim schematem.
Metoda 4: Używanie ciągów połączeń (format URI)
PostgreSQL obsługuje format URI połączenia libpq, który zawiera wszystkie parametry połączenia w jednym ciągu. Jest to preferowana metoda dla konfiguracji aplikacji, potoków CI/CD i narzędzi infrastruktury jako kodu.
psql "postgresql://appuser:password@localhost:5432/myapp_db"Lub używając schematu postgres:// (oba są prawidłowe):
psql "postgres://appuser:password@db.example.com:5432/analytics?sslmode=require"Parametr ?sslmode=require wymusza szyfrowanie TLS połączenia — jest to bezwzględny wymóg dla każdej bazy danych dostępnej spoza localhost. Jeśli hostujesz PostgreSQL na VPS lub serwerze dedykowanym, zawsze łącz ciągi połączeń z sslmode=require lub sslmode=verify-full i ważnym certyfikatem SSL.
Godne uwagi parametry URI połączenia:
| Parametr | Przeznaczenie | Przykładowa wartość |
|---|---|---|
sslmode | Poziom wymuszania TLS | require, verify-full |
connect_timeout | Sekundy przed niepowodzeniem połączenia | 10 |
application_name | Identyfikuje klienta w pg_stat_activity | myapp_worker |
options | Przekazuje parametry GUC po stronie serwera | -c search_path=myschema |
Metoda 5: Używanie psql ze zmiennymi środowiskowymi
W przypadku wielokrotnych połączeń z tym samym klastrem ustaw zmienne środowiskowe, aby uniknąć wielokrotnego wpisywania danych uwierzytelniających:
export PGHOST=localhost
export PGPORT=5432
export PGUSER=postgres
export PGPASSWORD=secret # Use .pgpass file in production instead
export PGDATABASE=myapp_db
psqlW środowisku produkcyjnym użyj pliku .pgpass zamiast PGPASSWORD, aby uniknąć ujawniania danych uwierzytelniających w historii powłoki lub listach procesów:
# ~/.pgpass format: hostname:port:database:username:password
localhost:5432:myapp_db:appuser:strongpasswordUstaw odpowiednie uprawnienia, w przeciwnym razie PostgreSQL zignoruje plik:
chmod 600 ~/.pgpassPorównanie: metody przełączania baz danych
| Metoda | Kontekst | Wymaga nowego procesu | Obsługuje zmianę użytkownika | Skryptowalność |
|---|---|---|---|---|
q + psql -d | Powłoka | Tak | Tak | Tak |
c dbname | psql interaktywny | Nie (psql obsługuje to) | Tak | Ograniczona |
| URI połączenia | Powłoka / Aplikacja | Tak | Tak | Tak |
| Zmienne środowiskowe | Powłoka | Tak | Tak | Tak |
| pgAdmin GUI | Klient GUI | Nie | Tak | Nie |
| Pula połączeń (PgBouncer) | Aplikacja | Nie | Zależy od trybu | Tak |
Efektywne zarządzanie wieloma połączeniami z bazami danych
Używanie pgAdmin do nawigacji opartej na GUI
pgAdmin wyświetla wszystkie bazy danych pod każdym zarejestrowanym serwerem w drzewie obiektów po lewej stronie. Kliknięcie bazy danych i otwarcie narzędzia Query Tool automatycznie ogranicza wszystkie zapytania do tej bazy danych. Jest to przydatne do pracy eksploracyjnej, ale nie nadaje się do automatyzacji.
Pułapka: pgAdmin utrzymuje oddzielne sloty połączeń dla każdej bazy danych. Jeśli serwer PostgreSQL ma niskie ustawienie max_connections (domyślnie 100), otwieranie wielu baz danych w pgAdmin może wyczerpać pulę połączeń, zanim aplikacja w ogóle się uruchomi.
Używanie PgBouncer do puli połączeń
W środowiskach produkcyjnych z częstym przełączaniem baz danych, pula połączeń taka jak PgBouncer znacznie redukuje narzut. PgBouncer działa w trzech trybach:
- Tryb sesji: Jedno połączenie serwera na sesję klienta. Funkcjonalnie równoważny bezpośrednim połączeniom.
- Tryb transakcji: Połączenie serwera jest utrzymywane tylko podczas transakcji. Najbardziej wydajny dla obciążeń OLTP.
- Tryb instrukcji: Połączenie zwracane po każdej instrukcji. Niekompatybilny z transakcjami wieloinstrukcyjnymi.
Przy uruchamianiu wielu baz danych aplikacji na jednej instancji PostgreSQL — co jest powszechnym wzorcem na hostingu VPS lub VPS z cPanel — PgBouncer w trybie transakcji może zmniejszyć liczbę aktywnych procesów backendowych o rząd wielkości.
Zapytania między bazami danych z dblink i postgres_fdw
Ponieważ sesje są ograniczone do bazy danych, zapytania o dane między bazami danych wymagają rozszerzenia. PostgreSQL oferuje dwie opcje:
dblink — starsze, proceduralne podejście:
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 — nowoczesny, zgodny ze standardami Foreign Data Wrapper:
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');Po konfiguracji remote_events zachowuje się jak tabela lokalna. postgres_fdw obsługuje pushdown predykatów, co oznacza, że klauzule WHERE są wykonywane na serwerze zdalnym, a nie lokalnie — kluczowe rozróżnienie wydajnościowe dla dużych zbiorów danych.
Systemowe bazy danych: czego nie wolno dotykać
PostgreSQL dostarcza cztery bazy danych w każdym nowym klastrze:
| Baza danych | Przeznaczenie | Bezpieczne do połączenia? | Bezpieczne do modyfikacji? |
|---|---|---|---|
postgres | Domyślna baza danych administratora | Tak | Z ostrożnością |
template1 | Szablon dla CREATE DATABASE | Tak | Tak, zmiany są propagowane |
template0 | Czysty bazowy szablon | Rzadko | Nie |
pg_catalog | Nie jest bazą danych, lecz schematem | N/D | Nigdy |
template1 jest klonowany za każdym razem, gdy uruchamiasz CREATE DATABASE bez podania szablonu. Jeśli instalujesz rozszerzenia lub tworzysz schematy w template1, każda nowa baza danych je dziedziczy. Jest to przydatne do standaryzacji środowisk, ale niebezpieczne, jeśli zrobione przypadkowo.
template0 istnieje jako nieskazitelny punkt awaryjny. Jest to jedyny szablon, który można użyć podczas przywracania archiwum pg_dump z innym kodowaniem lub ustawieniami regionalnymi, ponieważ nie zawiera obiektów tworzonych przez użytkownika, które mogłyby powodować konflikty.
Uprawnienia, pg_hba.conf i błędy połączeń
Częstym źródłem zamieszania przy przełączaniu baz danych jest rozróżnienie między uprawnieniami na poziomie roli PostgreSQL a regułami uwierzytelniania pg_hba.conf. Oba muszą niezależnie zezwalać na połączenie.
Sprawdzenie na poziomie roli: Rola musi mieć uprawnienie CONNECT do docelowej bazy danych:
GRANT CONNECT ON DATABASE target_database TO appuser;Sprawdzenie pg_hba.conf: Plik uwierzytelniania opartego na hoście (/etc/postgresql/15/main/pg_hba.conf w Debian/Ubuntu) musi zawierać pasującą regułę dla użytkownika, bazy danych i adresu źródłowego. Typowy wpis:
# TYPE DATABASE USER ADDRESS METHOD
host myapp_db appuser 10.0.0.0/8 scram-sha-256Po edycji pg_hba.conf przeładuj konfigurację bez restartu serwera:
sudo systemctl reload postgresqlLub z poziomu psql:
SELECT pg_reload_conf();Typowy wzorzec błędu: Użytkownik ma uprawnienie CONNECT na poziomie SQL, ale pg_hba.conf nie ma pasującej reguły. Komunikat o błędzie (FATAL: no pg_hba.conf entry for host) jest jednoznaczny, ale programiści często całkowicie pomijają ten plik, ponieważ oczekują, że uprawnienia do bazy danych będą zarządzane wyłącznie przez SQL.
Praktyczna macierz decyzyjna
Użyj tej listy kontrolnej, aby wybrać właściwe podejście do połączenia dla swojego scenariusza:
- Interaktywna eksploracja na lokalnej maszynie deweloperskiej: Użyj
c dbnamewewnątrzpsql. Szybkie, bez nowego procesu. - Skrypt powłoki iterujący po wielu bazach danych: Użyj
psql -U postgres -d $dbname -c "..."w pętli z-t -Adla czystych danych wyjściowych. - Aplikacja łącząca się z jedną bazą danych: Użyj URI połączenia z
sslmode=requirei pulą połączeń (PgBouncer lub wbudowane poolowanie sterownika). - Aplikacja potrzebująca danych z dwóch baz danych: Zaimplementuj
postgres_fdwna głównej bazie danych zamiast zarządzać dwiema oddzielnymi pulami połączeń w kodzie aplikacji. - Weryfikacja RLS lub izolacji uprawnień: Użyj
c dbname role_name, aby podszyć się pod docelową rolę bez opuszczaniapsql. - Automatyczne provisionowanie / infrastruktura jako kod: Użyj zmiennych środowiskowych lub
.pgpassz kontem serwisowym; nigdy nie umieszczaj danych uwierzytelniających na stałe w skryptach. - Produkcyjne obciążenie o wysokiej współbieżności: Wdróż PgBouncer w trybie transakcji między aplikacją a PostgreSQL. Na serwerze dedykowanym dostosuj
max_connectionswpostgresql.confdo pojemności pamięci sprzętu (każdy backend używa około 5–10 MB RAM). - SaaS wielodostępny z bazami danych per tenant: Rozważ wielodostępność opartą na schematach w ramach jednej bazy danych zamiast baz danych per tenant, aby uniknąć fragmentacji puli połączeń i uprościć strategie tworzenia kopii zapasowych.
Dla zespołów uruchamiających PostgreSQL razem z aplikacjami webowymi, połączenie serwera bazy danych z odpowiednio skonfigurowanym środowiskiem hostingu współdzielonego lub VPS oraz zarejestrowaną domeną dla warstwy aplikacji uzupełnia standardowy stos produkcyjny.
FAQ
Czy mogę przełączyć bazę danych bez zamykania sesji psql?
Tak. Użyj meta-polecenia c target_database wewnątrz psql. Zamyka ono bieżące połączenie backendowe i otwiera nowe do wskazanej bazy danych, wszystko w ramach tej samej sesji terminala. Opcjonalnie możesz podać innego użytkownika, hosta i port w tym samym poleceniu.
Dlaczego PostgreSQL nie ma polecenia USE jak MySQL?
Architektura PostgreSQL wiąże proces backendowy z jedną bazą danych podczas uruchamiania. Katalog systemowy bazy danych jest ładowany do pamięci współdzielonej dla tego procesu, a przełączanie katalogów w trakcie sesji jest architektonicznie równoważne uruchomieniu nowego procesu. Polecenie c w psql jest praktycznym odpowiednikiem — po prostu sprawia, że restart procesu jest przezroczysty dla użytkownika.
Jak wykonywać zapytania o dane z dwóch różnych baz danych PostgreSQL jednocześnie?
Użyj rozszerzenia postgres_fdw, aby utworzyć serwer zewnętrzny i tabele zewnętrzne mapowane na zdalną bazę danych. Po konfiguracji możesz łączyć tabele lokalne i zdalne w jednym zapytaniu za pomocą JOIN. Do jednorazowych zapytań dblink jest prostszy, ale mniej wydajny i trudniejszy w utrzymaniu.
Co się stanie, jeśli połączę się z template1 i ją zmodyfikuję?
Wszelkie obiekty tworzone w template1 — tabele, rozszerzenia, schematy — zostaną sklonowane do każdej nowej bazy danych utworzonej za pomocą CREATE DATABASE (chyba że TEMPLATE template0 zostanie jawnie podany). Jest to czasami zamierzone (np. wstępna instalacja uuid-ossp lub pgcrypto), ale przypadkowe modyfikacje mogą uszkodzić wszystkie następnie tworzone bazy danych.
Jak sprawdzić, z którą bazą danych jest połączona bieżąca sesja psql?
Uruchom następujące polecenie wewnątrz psql:
SELECT current_database();Lub sprawdź sam monit psql — domyślnie wyświetla dbname=# (superużytkownik) lub dbname=> (zwykły użytkownik), gdzie dbname to aktywna baza danych.
